From 24d7aeaf8a1dc13034884044139728045604fc37 Mon Sep 17 00:00:00 2001 From: "Eric S. Raymond" Date: Thu, 16 Feb 2017 11:59:50 -0500 Subject: [PATCH] Don Wood's 430-point Adventure 2.5 from 1995, from rec.games.int-fiction. --- Makefile | 23 + actions1.c | 589 +++++++++++++ actions2.c | 352 ++++++++ adventure.text | 2295 ++++++++++++++++++++++++++++++++++++++++++++++++ copyright | 6 + datime.c | 50 ++ funcs.h | 40 + init.c | 708 +++++++++++++++ main.c | 859 ++++++++++++++++++ main.h | 4 + misc.c | 1019 +++++++++++++++++++++ misc.h | 78 ++ score.c | 119 +++ share.h | 24 + 14 files changed, 6166 insertions(+) create mode 100644 Makefile create mode 100644 actions1.c create mode 100644 actions2.c create mode 100644 adventure.text create mode 100644 copyright create mode 100644 datime.c create mode 100644 funcs.h create mode 100644 init.c create mode 100644 main.c create mode 100644 main.h create mode 100644 misc.c create mode 100644 misc.h create mode 100644 score.c create mode 100644 share.h diff --git a/Makefile b/Makefile new file mode 100644 index 0000000..1b88b81 --- /dev/null +++ b/Makefile @@ -0,0 +1,23 @@ +# NOTE: This version of Adventure was developed by the author on private +# equipment, and has been ported to Sun for entertainment purposes only. +# The author (Don Woods) retains full rights to the work. + +OBJS=main.o init.o actions1.o actions2.o score.o misc.o datime.o + +.c.o: + gcc -O $(DBX) -c $< + +adventure: $(OBJS) + gcc -O $(DBX) -o adventure $(OBJS) + +main.o: misc.h funcs.h + +init.o: misc.h main.h share.h funcs.h + +actions1.o: misc.h main.h share.h funcs.h + +actions2.o: misc.h main.h share.h funcs.h + +score.o: misc.h main.h share.h + +misc.o: misc.h main.h diff --git a/actions1.c b/actions1.c new file mode 100644 index 0000000..57e8cb1 --- /dev/null +++ b/actions1.c @@ -0,0 +1,589 @@ +#include "misc.h" +#include "main.h" +#include "share.h" +#include "funcs.h" + +#define TRUE (0==0) +#define FALSE (0!=0) + +extern carry(), discard(long), attack(), throw(), feed(), fill(); + +/* This stuff was broken off as part of an effort to get the main program + * to compile without running out of memory. We're called with a number + * that says what label the caller wanted to "goto", and we return a + * similar label number for the caller to "goto". + */ + +/* ANALYSE A VERB. REMEMBER WHAT IT WAS, GO BACK FOR OBJECT IF SECOND WORD + * UNLESS VERB IS "SAY", WHICH SNARFS ARBITRARY SECOND WORD. */ + +action(STARTAT)long STARTAT; { + switch(STARTAT) { + case 4000: goto L4000; + case 4090: goto L4090; + case 5000: goto L5000; + } + BUG(99); + +L4000: VERB=K; + SPK=ACTSPK[VERB]; + if(WD2 > 0 && VERB != SAY) return(2800); + if(VERB == SAY)OBJ=WD2; + if(OBJ > 0) goto L4090; + +/* ANALYSE AN INTRANSITIVE VERB (IE, NO OBJECT GIVEN YET). */ + +L4080: switch (VERB-1) { case 0: goto L8010; case 1: return(8000); case 2: + return(8000); case 3: goto L8040; case 4: return(2009); case 5: goto L8040; + case 6: goto L8070; case 7: goto L8080; case 8: return(8000); case + 9: return(8000); case 10: return(2011); case 11: goto L9120; case 12: + goto L9130; case 13: goto L8140; case 14: goto L9150; case 15: + return(8000); case 16: return(8000); case 17: goto L8180; case 18: + return(8000); case 19: goto L8200; case 20: return(8000); case 21: + goto L9220; case 22: goto L9230; case 23: goto L8240; case 24: + goto L8250; case 25: goto L8260; case 26: goto L8270; case 27: + return(8000); case 28: return(8000); case 29: goto L8300; case 30: + goto L8310; case 31: goto L8320; case 32: goto L8330; case 33: + goto L8340; } +/* TAKE DROP SAY OPEN NOTH LOCK ON OFF WAVE CALM + * WALK KILL POUR EAT DRNK RUB TOSS QUIT FIND INVN + * FEED FILL BLST SCOR FOO BRF READ BREK WAKE SUSP + * RESU FLY LSTN ZZZZ */ + BUG(23); + +/* ANALYSE A TRANSITIVE VERB. */ + +L4090: switch (VERB-1) { case 0: goto L9010; case 1: goto L9020; case 2: goto + L9030; case 3: goto L9040; case 4: return(2009); case 5: goto L9040; + case 6: goto L9070; case 7: goto L9080; case 8: goto L9090; case + 9: return(2011); case 10: return(2011); case 11: goto L9120; case 12: + goto L9130; case 13: goto L9140; case 14: goto L9150; case 15: + goto L9160; case 16: goto L9170; case 17: return(2011); case 18: + goto L9190; case 19: goto L9190; case 20: goto L9210; case 21: + goto L9220; case 22: goto L9230; case 23: return(2011); case 24: + return(2011); case 25: return(2011); case 26: goto L9270; case 27: + goto L9280; case 28: goto L9290; case 29: return(2011); case 30: + return(2011); case 31: goto L9320; case 32: return(2011); case 33: + goto L8340; } +/* TAKE DROP SAY OPEN NOTH LOCK ON OFF WAVE CALM + * WALK KILL POUR EAT DRNK RUB TOSS QUIT FIND INVN + * FEED FILL BLST SCOR FOO BRF READ BREK WAKE SUSP + * RESU FLY LSTN ZZZZ */ + BUG(24); + +/* ANALYSE AN OBJECT WORD. SEE IF THE THING IS HERE, WHETHER WE'VE GOT A VERB + * YET, AND SO ON. OBJECT MUST BE HERE UNLESS VERB IS "FIND" OR "INVENT(ORY)" + * (AND NO NEW VERB YET TO BE ANALYSED). WATER AND OIL ARE ALSO FUNNY, SINCE + * THEY ARE NEVER ACTUALLY DROPPED AT ANY LOCATION, BUT MIGHT BE HERE INSIDE + * THE BOTTLE OR URN OR AS A FEATURE OF THE LOCATION. */ + +L5000: OBJ=K; + if(!HERE(K)) goto L5100; +L5010: if(WD2 > 0) return(2800); + if(VERB != 0) goto L4090; + SETPRM(1,WD1,WD1X); + RSPEAK(255); + return(2600); + +L5100: if(K != GRATE) goto L5110; + if(LOC == 1 || LOC == 4 || LOC == 7)K=DPRSSN; + if(LOC > 9 && LOC < 15)K=ENTRNC; + if(K != GRATE) return(8); +L5110: if(K == DWARF && ATDWRF(LOC) > 0) goto L5010; + if((LIQ(0) == K && HERE(BOTTLE)) || K == LIQLOC(LOC)) goto L5010; + if(OBJ != OIL || !HERE(URN) || PROP[URN] == 0) goto L5120; + OBJ=URN; + goto L5010; +L5120: if(OBJ != PLANT || !AT(PLANT2) || PROP[PLANT2] == 0) goto L5130; + OBJ=PLANT2; + goto L5010; +L5130: if(OBJ != KNIFE || KNFLOC != LOC) goto L5140; + KNFLOC= -1; + SPK=116; + return(2011); +L5140: if(OBJ != ROD || !HERE(ROD2)) goto L5190; + OBJ=ROD2; + goto L5010; +L5190: if((VERB == FIND || VERB == INVENT) && WD2 <= 0) goto L5010; + SETPRM(1,WD1,WD1X); + RSPEAK(256); + return(2012); + + + + +/* ROUTINES FOR PERFORMING THE VARIOUS ACTION VERBS */ + +/* STATEMENT NUMBERS IN THIS SECTION ARE 8000 FOR INTRANSITIVE VERBS, 9000 FOR + * TRANSITIVE, PLUS TEN TIMES THE VERB NUMBER. MANY INTRANSITIVE VERBS USE THE + * TRANSITIVE CODE, AND SOME VERBS USE CODE FOR OTHER VERBS, AS NOTED BELOW. */ + +/* CARRY, NO OBJECT GIVEN YET. OK IF ONLY ONE OBJECT PRESENT. */ + +L8010: if(ATLOC[LOC] == 0 || LINK[ATLOC[LOC]] != 0 || ATDWRF(LOC) > 0) return(8000); + OBJ=ATLOC[LOC]; + +/* TRANSITIVE CARRY/DROP ARE IN SEPARATE FILE. */ + +L9010: return(carry()); +L9020: return(discard(FALSE)); + +/* SAY. ECHO WD2 (OR WD1 IF NO WD2 (SAY WHAT?, ETC.).) MAGIC WORDS OVERRIDE. */ + +L9030: SETPRM(1,WD2,WD2X); + if(WD2 <= 0)SETPRM(1,WD1,WD1X); + if(WD2 > 0)WD1=WD2; + I=VOCAB(WD1,-1); + if(I == 62 || I == 65 || I == 71 || I == 2025 || I == 2034) goto L9035; + RSPEAK(258); + return(2012); + +L9035: WD2=0; + OBJ=0; + return(2630); + +/* LOCK, UNLOCK, NO OBJECT GIVEN. ASSUME VARIOUS THINGS IF PRESENT. */ + +L8040: SPK=28; + if(HERE(CLAM))OBJ=CLAM; + if(HERE(OYSTER))OBJ=OYSTER; + if(AT(DOOR))OBJ=DOOR; + if(AT(GRATE))OBJ=GRATE; + if(OBJ != 0 && HERE(CHAIN)) return(8000); + if(HERE(CHAIN))OBJ=CHAIN; + if(OBJ == 0) return(2011); + +/* LOCK, UNLOCK OBJECT. SPECIAL STUFF FOR OPENING CLAM/OYSTER AND FOR CHAIN. */ + +L9040: if(OBJ == CLAM || OBJ == OYSTER) goto L9046; + if(OBJ == DOOR)SPK=111; + if(OBJ == DOOR && PROP[DOOR] == 1)SPK=54; + if(OBJ == CAGE)SPK=32; + if(OBJ == KEYS)SPK=55; + if(OBJ == GRATE || OBJ == CHAIN)SPK=31; + if(SPK != 31 || !HERE(KEYS)) return(2011); + if(OBJ == CHAIN) goto L9048; + if(!CLOSNG) goto L9043; + K=130; + if(!PANIC)CLOCK2=15; + PANIC=TRUE; + return(2010); + +L9043: K=34+PROP[GRATE]; + PROP[GRATE]=1; + if(VERB == LOCK)PROP[GRATE]=0; + K=K+2*PROP[GRATE]; + return(2010); + +/* CLAM/OYSTER. */ +L9046: K=0; + if(OBJ == OYSTER)K=1; + SPK=124+K; + if(TOTING(OBJ))SPK=120+K; + if(!TOTING(TRIDNT))SPK=122+K; + if(VERB == LOCK)SPK=61; + if(SPK != 124) return(2011); + DSTROY(CLAM); + DROP(OYSTER,LOC); + DROP(PEARL,105); + return(2011); + +/* CHAIN. */ +L9048: if(VERB == LOCK) goto L9049; + SPK=171; + if(PROP[BEAR] == 0)SPK=41; + if(PROP[CHAIN] == 0)SPK=37; + if(SPK != 171) return(2011); + PROP[CHAIN]=0; + FIXED[CHAIN]=0; + if(PROP[BEAR] != 3)PROP[BEAR]=2; + FIXED[BEAR]=2-PROP[BEAR]; + return(2011); + +L9049: SPK=172; + if(PROP[CHAIN] != 0)SPK=34; + if(LOC != PLAC[CHAIN])SPK=173; + if(SPK != 172) return(2011); + PROP[CHAIN]=2; + if(TOTING(CHAIN))DROP(CHAIN,LOC); + FIXED[CHAIN]= -1; + return(2011); + +/* LIGHT. APPLICABLE ONLY TO LAMP AND URN. */ + +L8070: if(HERE(LAMP) && PROP[LAMP] == 0 && LIMIT >= 0)OBJ=LAMP; + if(HERE(URN) && PROP[URN] == 1)OBJ=OBJ*100+URN; + if(OBJ == 0 || OBJ > 100) return(8000); + +L9070: if(OBJ == URN) goto L9073; + if(OBJ != LAMP) return(2011); + SPK=184; + if(LIMIT < 0) return(2011); + PROP[LAMP]=1; + RSPEAK(39); + if(WZDARK) return(2000); + return(2012); + +L9073: SPK=38; + if(PROP[URN] == 0) return(2011); + SPK=209; + PROP[URN]=2; + return(2011); + +/* EXTINGUISH. LAMP, URN, DRAGON/VOLCANO (NICE TRY). */ + +L8080: if(HERE(LAMP) && PROP[LAMP] == 1)OBJ=LAMP; + if(HERE(URN) && PROP[URN] == 2)OBJ=OBJ*100+URN; + if(OBJ == 0 || OBJ > 100) return(8000); + +L9080: if(OBJ == URN) goto L9083; + if(OBJ == LAMP) goto L9086; + if(OBJ == DRAGON || OBJ == VOLCAN)SPK=146; + return(2011); + +L9083: PROP[URN]=PROP[URN]/2; + SPK=210; + return(2011); + +L9086: PROP[LAMP]=0; + RSPEAK(40); + if(DARK(0))RSPEAK(16); + return(2012); + +/* WAVE. NO EFFECT UNLESS WAVING ROD AT FISSURE OR AT BIRD. */ + +L9090: if((!TOTING(OBJ)) && (OBJ != ROD || !TOTING(ROD2)))SPK=29; + if(OBJ != ROD || !TOTING(OBJ) || (!HERE(BIRD) && (CLOSNG || !AT(FISSUR)))) + return(2011); + if(HERE(BIRD))SPK=206+MOD(PROP[BIRD],2); + if(SPK == 206 && LOC == PLACE[STEPS] && PROP[JADE] < 0) goto L9094; + if(CLOSED) return(18999); + if(CLOSNG || !AT(FISSUR)) return(2011); + if(HERE(BIRD))RSPEAK(SPK); + PROP[FISSUR]=1-PROP[FISSUR]; + PSPEAK(FISSUR,2-PROP[FISSUR]); + return(2012); + +L9094: DROP(JADE,LOC); + PROP[JADE]=0; + TALLY=TALLY-1; + SPK=208; + return(2011); + +/* ATTACK ALSO MOVED INTO SEPARATE MODULE. */ + +L9120: return(attack()); + +/* POUR. IF NO OBJECT, OR OBJECT IS BOTTLE, ASSUME CONTENTS OF BOTTLE. + * SPECIAL TESTS FOR POURING WATER OR OIL ON PLANT OR RUSTY DOOR. */ + +L9130: if(OBJ == BOTTLE || OBJ == 0)OBJ=LIQ(0); + if(OBJ == 0) return(8000); + if(!TOTING(OBJ)) return(2011); + SPK=78; + if(OBJ != OIL && OBJ != WATER) return(2011); + if(HERE(URN) && PROP[URN] == 0) goto L9134; + PROP[BOTTLE]=1; + PLACE[OBJ]=0; + SPK=77; + if(!(AT(PLANT) || AT(DOOR))) return(2011); + + if(AT(DOOR)) goto L9132; + SPK=112; + if(OBJ != WATER) return(2011); + PSPEAK(PLANT,PROP[PLANT]+3); + PROP[PLANT]=MOD(PROP[PLANT]+1,3); + PROP[PLANT2]=PROP[PLANT]; + K=NUL; + return(8); + +L9132: PROP[DOOR]=0; + if(OBJ == OIL)PROP[DOOR]=1; + SPK=113+PROP[DOOR]; + return(2011); + +L9134: OBJ=URN; + goto L9220; + +/* EAT. INTRANSITIVE: ASSUME FOOD IF PRESENT, ELSE ASK WHAT. TRANSITIVE: FOOD + * OK, SOME THINGS LOSE APPETITE, REST ARE RIDICULOUS. */ + +L8140: if(!HERE(FOOD)) return(8000); +L8142: DSTROY(FOOD); + SPK=72; + return(2011); + +L9140: if(OBJ == FOOD) goto L8142; + if(OBJ == BIRD || OBJ == SNAKE || OBJ == CLAM || OBJ == OYSTER || OBJ == + DWARF || OBJ == DRAGON || OBJ == TROLL || OBJ == BEAR || OBJ == + OGRE)SPK=71; + return(2011); + +/* DRINK. IF NO OBJECT, ASSUME WATER AND LOOK FOR IT HERE. IF WATER IS IN + * THE BOTTLE, DRINK THAT, ELSE MUST BE AT A WATER LOC, SO DRINK STREAM. */ + +L9150: if(OBJ == 0 && LIQLOC(LOC) != WATER && (LIQ(0) != WATER || !HERE(BOTTLE))) + return(8000); + if(OBJ == BLOOD) goto L9153; + if(OBJ != 0 && OBJ != WATER)SPK=110; + if(SPK == 110 || LIQ(0) != WATER || !HERE(BOTTLE)) return(2011); + PROP[BOTTLE]=1; + PLACE[WATER]=0; + SPK=74; + return(2011); + +L9153: DSTROY(BLOOD); + PROP[DRAGON]=2; + OBJSND[BIRD]=OBJSND[BIRD]+3; + SPK=240; + return(2011); + +/* RUB. YIELDS VARIOUS SNIDE REMARKS EXCEPT FOR LIT URN. */ + +L9160: if(OBJ != LAMP)SPK=76; + if(OBJ != URN || PROP[URN] != 2) return(2011); + DSTROY(URN); + DROP(AMBER,LOC); + PROP[AMBER]=1; + TALLY=TALLY-1; + DROP(CAVITY,LOC); + SPK=216; + return(2011); + +/* THROW MOVED INTO SEPARATE MODULE. */ + +L9170: return(throw()); + +/* QUIT. INTRANSITIVE ONLY. VERIFY INTENT AND EXIT IF THAT'S WHAT HE WANTS. */ + +L8180: if(YES(22,54,54)) score(1); + return(2012); + +/* FIND. MIGHT BE CARRYING IT, OR IT MIGHT BE HERE. ELSE GIVE CAVEAT. */ + +L9190: if(AT(OBJ) || (LIQ(0) == OBJ && AT(BOTTLE)) || K == LIQLOC(LOC) || (OBJ == + DWARF && ATDWRF(LOC) > 0))SPK=94; + if(CLOSED)SPK=138; + if(TOTING(OBJ))SPK=24; + return(2011); + +/* INVENTORY. IF OBJECT, TREAT SAME AS FIND. ELSE REPORT ON CURRENT BURDEN. */ + +L8200: SPK=98; + /* 8201 */ for (I=1; I<=100; I++) { + if(I == BEAR || !TOTING(I)) goto L8201; + if(SPK == 98)RSPEAK(99); + BLKLIN=FALSE; + PSPEAK(I,-1); + BLKLIN=TRUE; + SPK=0; +L8201: /*etc*/ ; + } /* end loop */ + if(TOTING(BEAR))SPK=141; + return(2011); + +/* FEED/FILL ARE IN THE OTHER MODULE. */ + +L9210: return(feed()); +L9220: return(fill()); + +/* BLAST. NO EFFECT UNLESS YOU'VE GOT DYNAMITE, WHICH IS A NEAT TRICK! */ + +L9230: if(PROP[ROD2] < 0 || !CLOSED) return(2011); + BONUS=133; + if(LOC == 115)BONUS=134; + if(HERE(ROD2))BONUS=135; + RSPEAK(BONUS); + score(0); + +/* SCORE. CALL SCORING ROUTINE BUT TELL IT TO RETURN. */ + +L8240: score(-1); + SETPRM(1,SCORE,MXSCOR); + SETPRM(3,TURNS,TURNS); + RSPEAK(259); + return(2012); + +/* FEE FIE FOE FOO (AND FUM). ADVANCE TO NEXT STATE IF GIVEN IN PROPER ORDER. + * LOOK UP WD1 IN SECTION 3 OF VOCAB TO DETERMINE WHICH WORD WE'VE GOT. LAST + * WORD ZIPS THE EGGS BACK TO THE GIANT ROOM (UNLESS ALREADY THERE). */ + +L8250: K=VOCAB(WD1,3); + SPK=42; + if(FOOBAR == 1-K) goto L8252; + if(FOOBAR != 0)SPK=151; + return(2011); + +L8252: FOOBAR=K; + if(K != 4) return(2009); + FOOBAR=0; + if(PLACE[EGGS] == PLAC[EGGS] || (TOTING(EGGS) && LOC == PLAC[EGGS])) + return(2011); +/* BRING BACK TROLL IF WE STEAL THE EGGS BACK FROM HIM BEFORE CROSSING. */ + if(PLACE[EGGS] == 0 && PLACE[TROLL] == 0 && PROP[TROLL] == + 0)PROP[TROLL]=1; + K=2; + if(HERE(EGGS))K=1; + if(LOC == PLAC[EGGS])K=0; + MOVE(EGGS,PLAC[EGGS]); + PSPEAK(EGGS,K); + return(2012); + +/* BRIEF. INTRANSITIVE ONLY. SUPPRESS LONG DESCRIPTIONS AFTER FIRST TIME. */ + +L8260: SPK=156; + ABBNUM=10000; + DETAIL=3; + return(2011); + +/* READ. PRINT STUFF BASED ON OBJTXT. OYSTER (?) IS SPECIAL CASE. */ + +L8270: /* 8275 */ for (I=1; I<=100; I++) { +L8275: if(HERE(I) && OBJTXT[I] != 0 && PROP[I] >= 0)OBJ=OBJ*100+I; + } /* end loop */ + if(OBJ > 100 || OBJ == 0 || DARK(0)) return(8000); + +L9270: if(DARK(0)) goto L5190; + if(OBJTXT[OBJ] == 0 || PROP[OBJ] < 0) return(2011); + if(OBJ == OYSTER && !CLSHNT) goto L9275; + PSPEAK(OBJ,OBJTXT[OBJ]+PROP[OBJ]); + return(2012); + +L9275: CLSHNT=YES(192,193,54); + return(2012); + +/* BREAK. ONLY WORKS FOR MIRROR IN REPOSITORY AND, OF COURSE, THE VASE. */ + +L9280: if(OBJ == MIRROR)SPK=148; + if(OBJ == VASE && PROP[VASE] == 0) goto L9282; + if(OBJ != MIRROR || !CLOSED) return(2011); + SPK=197; + return(18999); + +L9282: SPK=198; + if(TOTING(VASE))DROP(VASE,LOC); + PROP[VASE]=2; + FIXED[VASE]= -1; + return(2011); + +/* WAKE. ONLY USE IS TO DISTURB THE DWARVES. */ + +L9290: if(OBJ != DWARF || !CLOSED) return(2011); + SPK=199; + return(18999); + +/* SUSPEND. OFFER TO SAVE THINGS IN A FILE, BUT CHARGING SOME POINTS (SO + * CAN'T WIN BY USING SAVED GAMES TO RETRY BATTLES OR TO START OVER AFTER + * LEARNING ZZWORD). */ + +L8300: SPK=201; + RSPEAK(260); + if(!YES(200,54,54)) return(2012); + SAVED=SAVED+5; + KK= -1; + +/* THIS NEXT PART IS SHARED WITH THE "RESUME" CODE. THE TWO CASES ARE + * DISTINGUISHED BY THE VALUE OF KK (-1 FOR SUSPEND, +1 FOR RESUME). */ + +L8305: DATIME(I,K); + K=I+650*K; + SAVWRD(KK,K); + K=VRSION; + SAVWRD(0,K); + if(K != VRSION) goto L8312; +/* HEREWITH ARE ALL THE VARIABLES WHOSE VALUES CAN CHANGE DURING A GAME, + * OMITTING A FEW (SUCH AS I, J, ATTACK) WHOSE VALUES BETWEEN TURNS ARE + * IRRELEVANT AND SOME WHOSE VALUES WHEN A GAME IS + * SUSPENDED OR RESUMED ARE GUARANTEED TO MATCH. IF UNSURE WHETHER A VALUE + * NEEDS TO BE SAVED, INCLUDE IT. OVERKILL CAN'T HURT. PAD THE LAST SAVWDS + * WITH JUNK VARIABLES TO BRING IT UP TO 7 VALUES. */ + SAVWDS(ABBNUM,BLKLIN,BONUS,CLOCK1,CLOCK2,CLOSED,CLOSNG); + SAVWDS(DETAIL,DFLAG,DKILL,DTOTAL,FOOBAR,HOLDNG,IWEST); + SAVWDS(KNFLOC,LIMIT,LL,LMWARN,LOC,NEWLOC,NUMDIE); + SAVWDS(OBJ,OLDLC2,OLDLOC,OLDOBJ,PANIC,SAVED,SETUP); + SAVWDS(SPK,TALLY,THRESH,TRNDEX,TRNLUZ,TURNS,OBJTXT[OYSTER]); + SAVWDS(VERB,WD1,WD1X,WD2,WZDARK,ZZWORD,OBJSND[BIRD]); + SAVWDS(OBJTXT[SIGN],CLSHNT,NOVICE,K,K,K,K); + SAVARR(ABB,LOCSIZ); + SAVARR(ATLOC,LOCSIZ); + SAVARR(DLOC,6); + SAVARR(DSEEN,6); + SAVARR(FIXED,100); + SAVARR(HINTED,HNTSIZ); + SAVARR(HINTLC,HNTSIZ); + SAVARR(LINK,200); + SAVARR(ODLOC,6); + SAVARR(PLACE,100); + SAVARR(PROP,100); + SAVWRD(KK,K); + if(K != 0) goto L8318; + K=NUL; + ZZWORD=RNDVOC(3,ZZWORD-MESH*2)+MESH*2; + if(KK > 0) return(8); + RSPEAK(266); + exit(FALSE); + +/* RESUME. READ A SUSPENDED GAME BACK FROM A FILE. */ + +L8310: KK=1; + if(LOC == 1 && ABB[1] == 1) goto L8305; + RSPEAK(268); + if(!YES(200,54,54)) return(2012); + goto L8305; + +L8312: SETPRM(1,K/10,MOD(K,10)); + SETPRM(3,VRSION/10,MOD(VRSION,10)); + RSPEAK(269); + return(2000); + +L8318: RSPEAK(270); + exit(FALSE); + +/* FLY. SNIDE REMARKS UNLESS HOVERING RUG IS HERE. */ + +L8320: if(PROP[RUG] != 2)SPK=224; + if(!HERE(RUG))SPK=225; + if(SPK/2 == 112) return(2011); + OBJ=RUG; + +L9320: if(OBJ != RUG) return(2011); + SPK=223; + if(PROP[RUG] != 2) return(2011); + OLDLC2=OLDLOC; + OLDLOC=LOC; + NEWLOC=PLACE[RUG]+FIXED[RUG]-LOC; + SPK=226; + if(PROP[SAPPH] >= 0)SPK=227; + RSPEAK(SPK); + return(2); + +/* LISTEN. INTRANSITIVE ONLY. PRINT STUFF BASED ON OBJSND/LOCSND. */ + +L8330: SPK=228; + K=LOCSND[LOC]; + if(K == 0) goto L8332; + RSPEAK(IABS(K)); + if(K < 0) return(2012); + SPK=0; +L8332: SETPRM(1,ZZWORD-MESH*2,0); + /* 8335 */ for (I=1; I<=100; I++) { + if(!HERE(I) || OBJSND[I] == 0 || PROP[I] < 0) goto L8335; + PSPEAK(I,OBJSND[I]+PROP[I]); + SPK=0; + if(I == BIRD && OBJSND[I]+PROP[I] == 8)DSTROY(BIRD); +L8335: /*etc*/ ; + } /* end loop */ + return(2011); + +/* Z'ZZZ (WORD GETS RECOMPUTED AT STARTUP; DIFFERENT EACH GAME). */ + +L8340: if(!AT(RESER) && LOC != FIXED[RESER]-1) return(2011); + PSPEAK(RESER,PROP[RESER]+1); + PROP[RESER]=1-PROP[RESER]; + if(AT(RESER)) return(2012); + OLDLC2=LOC; + NEWLOC=0; + RSPEAK(241); + return(2); + +} diff --git a/actions2.c b/actions2.c new file mode 100644 index 0000000..98be045 --- /dev/null +++ b/actions2.c @@ -0,0 +1,352 @@ +#include "misc.h" +#include "main.h" +#include "share.h" +#include "funcs.h" + +#define TRUE (0==0) +#define FALSE (0!=0) + +/* CARRY AN OBJECT. SPECIAL CASES FOR BIRD AND CAGE (IF BIRD IN CAGE, CAN'T + * TAKE ONE WITHOUT THE OTHER). LIQUIDS ALSO SPECIAL, SINCE THEY DEPEND ON + * STATUS OF BOTTLE. ALSO VARIOUS SIDE EFFECTS, ETC. */ + +carry() { + if(TOTING(OBJ)) return(2011); + SPK=25; + if(OBJ == PLANT && PROP[PLANT] <= 0)SPK=115; + if(OBJ == BEAR && PROP[BEAR] == 1)SPK=169; + if(OBJ == CHAIN && PROP[BEAR] != 0)SPK=170; + if(OBJ == URN)SPK=215; + if(OBJ == CAVITY)SPK=217; + if(OBJ == BLOOD)SPK=239; + if(OBJ == RUG && PROP[RUG] == 2)SPK=222; + if(OBJ == SIGN)SPK=196; + if(OBJ != MESSAG) goto L9011; + SPK=190; + DSTROY(MESSAG); +L9011: if(FIXED[OBJ] != 0) return(2011); + if(OBJ != WATER && OBJ != OIL) goto L9017; + K=OBJ; + OBJ=BOTTLE; + if(HERE(BOTTLE) && LIQ(0) == K) goto L9017; + if(TOTING(BOTTLE) && PROP[BOTTLE] == 1) return(fill()); + if(PROP[BOTTLE] != 1)SPK=105; + if(!TOTING(BOTTLE))SPK=104; + return(2011); +L9017: SPK=92; + if(HOLDNG >= 7) return(2011); + if(OBJ != BIRD || PROP[BIRD] == 1 || -1-PROP[BIRD] == 1) goto L9014; + if(PROP[BIRD] == 2) goto L9015; + if(!TOTING(CAGE))SPK=27; + if(TOTING(ROD))SPK=26; + if(SPK/2 == 13) return(2011); + PROP[BIRD]=1; +L9014: if((OBJ == BIRD || OBJ == CAGE) && (PROP[BIRD] == 1 || -1-PROP[BIRD] == + 1))CARRY(BIRD+CAGE-OBJ,LOC); + CARRY(OBJ,LOC); + K=LIQ(0); + if(OBJ == BOTTLE && K != 0)PLACE[K]= -1; + if(!GSTONE(OBJ) || PROP[OBJ] == 0) return(2009); + PROP[OBJ]=0; + PROP[CAVITY]=1; + return(2009); + +L9015: SPK=238; + DSTROY(BIRD); + return(2011); +} + +/* DISCARD OBJECT. "THROW" ALSO COMES HERE FOR MOST OBJECTS. SPECIAL CASES FOR + * BIRD (MIGHT ATTACK SNAKE OR DRAGON) AND CAGE (MIGHT CONTAIN BIRD) AND VASE. + * DROP COINS AT VENDING MACHINE FOR EXTRA BATTERIES. */ + +discard(just_do_it)long just_do_it; { + if(just_do_it) goto L9021; + if(TOTING(ROD2) && OBJ == ROD && !TOTING(ROD))OBJ=ROD2; + if(!TOTING(OBJ)) return(2011); + if(OBJ != BIRD || !HERE(SNAKE)) goto L9023; + RSPEAK(30); + if(CLOSED) return(19000); + DSTROY(SNAKE); +/* SET PROP FOR USE BY TRAVEL OPTIONS */ + PROP[SNAKE]=1; +L9021: K=LIQ(0); + if(K == OBJ)OBJ=BOTTLE; + if(OBJ == BOTTLE && K != 0)PLACE[K]=0; + if(OBJ == CAGE && PROP[BIRD] == 1)DROP(BIRD,LOC); + DROP(OBJ,LOC); + if(OBJ != BIRD) return(2012); + PROP[BIRD]=0; + if(FOREST(LOC))PROP[BIRD]=2; + return(2012); + +L9023: if(!(GSTONE(OBJ) && AT(CAVITY) && PROP[CAVITY] != 0)) goto L9024; + RSPEAK(218); + PROP[OBJ]=1; + PROP[CAVITY]=0; + if(!HERE(RUG) || !((OBJ == EMRALD && PROP[RUG] != 2) || (OBJ == RUBY && + PROP[RUG] == 2))) goto L9021; + SPK=219; + if(TOTING(RUG))SPK=220; + if(OBJ == RUBY)SPK=221; + RSPEAK(SPK); + if(SPK == 220) goto L9021; + K=2-PROP[RUG]; + PROP[RUG]=K; + if(K == 2)K=PLAC[SAPPH]; + MOVE(RUG+100,K); + goto L9021; + +L9024: if(OBJ != COINS || !HERE(VEND)) goto L9025; + DSTROY(COINS); + DROP(BATTER,LOC); + PSPEAK(BATTER,0); + return(2012); + +L9025: if(OBJ != BIRD || !AT(DRAGON) || PROP[DRAGON] != 0) goto L9026; + RSPEAK(154); + DSTROY(BIRD); + PROP[BIRD]=0; + return(2012); + +L9026: if(OBJ != BEAR || !AT(TROLL)) goto L9027; + RSPEAK(163); + MOVE(TROLL,0); + MOVE(TROLL+100,0); + MOVE(TROLL2,PLAC[TROLL]); + MOVE(TROLL2+100,FIXD[TROLL]); + JUGGLE(CHASM); + PROP[TROLL]=2; + goto L9021; + +L9027: if(OBJ == VASE && LOC != PLAC[PILLOW]) goto L9028; + RSPEAK(54); + goto L9021; + +L9028: PROP[VASE]=2; + if(AT(PILLOW))PROP[VASE]=0; + PSPEAK(VASE,PROP[VASE]+1); + if(PROP[VASE] != 0)FIXED[VASE]= -1; + goto L9021; +} + +/* ATTACK. ASSUME TARGET IF UNAMBIGUOUS. "THROW" ALSO LINKS HERE. ATTACKABLE + * OBJECTS FALL INTO TWO CATEGORIES: ENEMIES (SNAKE, DWARF, ETC.) AND OTHERS + * (BIRD, CLAM, MACHINE). AMBIGUOUS IF 2 ENEMIES, OR NO ENEMIES BUT 2 OTHERS. */ + +attack() { + I=ATDWRF(LOC); + if(OBJ != 0) goto L9124; + if(I > 0)OBJ=DWARF; + if(HERE(SNAKE))OBJ=OBJ*100+SNAKE; + if(AT(DRAGON) && PROP[DRAGON] == 0)OBJ=OBJ*100+DRAGON; + if(AT(TROLL))OBJ=OBJ*100+TROLL; + if(AT(OGRE))OBJ=OBJ*100+OGRE; + if(HERE(BEAR) && PROP[BEAR] == 0)OBJ=OBJ*100+BEAR; + if(OBJ > 100) return(8000); + if(OBJ != 0) goto L9124; +/* CAN'T ATTACK BIRD OR MACHINE BY THROWING AXE. */ + if(HERE(BIRD) && VERB != THROW)OBJ=BIRD; + if(HERE(VEND) && VERB != THROW)OBJ=OBJ*100+VEND; +/* CLAM AND OYSTER BOTH TREATED AS CLAM FOR INTRANSITIVE CASE; NO HARM DONE. */ + if(HERE(CLAM) || HERE(OYSTER))OBJ=100*OBJ+CLAM; + if(OBJ > 100) return(8000); +L9124: if(OBJ != BIRD) goto L9125; + SPK=137; + if(CLOSED) return(2011); + DSTROY(BIRD); + PROP[BIRD]=0; + SPK=45; +L9125: if(OBJ != VEND) goto L9126; + PSPEAK(VEND,PROP[VEND]+2); + PROP[VEND]=3-PROP[VEND]; + return(2012); + +L9126: if(OBJ == 0)SPK=44; + if(OBJ == CLAM || OBJ == OYSTER)SPK=150; + if(OBJ == SNAKE)SPK=46; + if(OBJ == DWARF)SPK=49; + if(OBJ == DWARF && CLOSED) return(19000); + if(OBJ == DRAGON)SPK=167; + if(OBJ == TROLL)SPK=157; + if(OBJ == OGRE)SPK=203; + if(OBJ == OGRE && I > 0) goto L9128; + if(OBJ == BEAR)SPK=165+(PROP[BEAR]+1)/2; + if(OBJ != DRAGON || PROP[DRAGON] != 0) return(2011); +/* FUN STUFF FOR DRAGON. IF HE INSISTS ON ATTACKING IT, WIN! SET PROP TO DEAD, + * MOVE DRAGON TO CENTRAL LOC (STILL FIXED), MOVE RUG THERE (NOT FIXED), AND + * MOVE HIM THERE, TOO. THEN DO A NULL MOTION TO GET NEW DESCRIPTION. */ + RSPEAK(49); + VERB=0; + OBJ=0; + GETIN(WD1,WD1X,WD2,WD2X); + if(WD1 != MAKEWD(25) && WD1 != MAKEWD(250519)) return(2607); + PSPEAK(DRAGON,3); + PROP[DRAGON]=1; + PROP[RUG]=0; + K=(PLAC[DRAGON]+FIXD[DRAGON])/2; + MOVE(DRAGON+100,-1); + MOVE(RUG+100,0); + MOVE(DRAGON,K); + MOVE(RUG,K); + DROP(BLOOD,K); + /* 9127 */ for (OBJ=1; OBJ<=100; OBJ++) { + if(PLACE[OBJ] == PLAC[DRAGON] || PLACE[OBJ] == FIXD[DRAGON])MOVE(OBJ,K); +L9127: /*etc*/ ; + } /* end loop */ + LOC=K; + K=NUL; + return(8); + +L9128: RSPEAK(SPK); + RSPEAK(6); + DSTROY(OGRE); + K=0; + /* 9129 */ for (I=1; I<=5; I++) { + if(DLOC[I] != LOC) goto L9129; + K=K+1; + DLOC[I]=61; + DSEEN[I]=FALSE; +L9129: /*etc*/ ; + } /* end loop */ + SPK=SPK+1+1/K; + return(2011); +} + +/* THROW. SAME AS DISCARD UNLESS AXE. THEN SAME AS ATTACK EXCEPT IGNORE BIRD, + * AND IF DWARF IS PRESENT THEN ONE MIGHT BE KILLED. (ONLY WAY TO DO SO!) + * AXE ALSO SPECIAL FOR DRAGON, BEAR, AND TROLL. TREASURES SPECIAL FOR TROLL. */ + +throw() { + if(TOTING(ROD2) && OBJ == ROD && !TOTING(ROD))OBJ=ROD2; + if(!TOTING(OBJ)) return(2011); + if(OBJ >= 50 && OBJ <= MAXTRS && AT(TROLL)) goto L9178; + if(OBJ == FOOD && HERE(BEAR)) goto L9177; + if(OBJ != AXE) return(discard(FALSE)); + I=ATDWRF(LOC); + if(I > 0) goto L9172; + SPK=152; + if(AT(DRAGON) && PROP[DRAGON] == 0) goto L9175; + SPK=158; + if(AT(TROLL)) goto L9175; + SPK=203; + if(AT(OGRE)) goto L9175; + if(HERE(BEAR) && PROP[BEAR] == 0) goto L9176; + OBJ=0; + return(attack()); + +L9172: SPK=48; + if(RAN(7) < DFLAG) goto L9175; + DSEEN[I]=FALSE; + DLOC[I]=0; + SPK=47; + DKILL=DKILL+1; + if(DKILL == 1)SPK=149; +L9175: RSPEAK(SPK); + DROP(AXE,LOC); + K=NUL; + return(8); + +/* THIS'LL TEACH HIM TO THROW THE AXE AT THE BEAR! */ +L9176: SPK=164; + DROP(AXE,LOC); + FIXED[AXE]= -1; + PROP[AXE]=1; + JUGGLE(BEAR); + return(2011); + +/* BUT THROWING FOOD IS ANOTHER STORY. */ +L9177: OBJ=BEAR; + return(feed()); + +L9178: SPK=159; +/* SNARF A TREASURE FOR THE TROLL. */ + DROP(OBJ,0); + MOVE(TROLL,0); + MOVE(TROLL+100,0); + DROP(TROLL2,PLAC[TROLL]); + DROP(TROLL2+100,FIXD[TROLL]); + JUGGLE(CHASM); + return(2011); +} + +/* FEED. IF BIRD, NO SEED. SNAKE, DRAGON, TROLL: QUIP. IF DWARF, MAKE HIM + * MAD. BEAR, SPECIAL. */ + +feed() { + if(OBJ != BIRD) goto L9212; + SPK=100; + return(2011); + +L9212: if(OBJ != SNAKE && OBJ != DRAGON && OBJ != TROLL) goto L9213; + SPK=102; + if(OBJ == DRAGON && PROP[DRAGON] != 0)SPK=110; + if(OBJ == TROLL)SPK=182; + if(OBJ != SNAKE || CLOSED || !HERE(BIRD)) return(2011); + SPK=101; + DSTROY(BIRD); + PROP[BIRD]=0; + return(2011); + +L9213: if(OBJ != DWARF) goto L9214; + if(!HERE(FOOD)) return(2011); + SPK=103; + DFLAG=DFLAG+2; + return(2011); + +L9214: if(OBJ != BEAR) goto L9215; + if(PROP[BEAR] == 0)SPK=102; + if(PROP[BEAR] == 3)SPK=110; + if(!HERE(FOOD)) return(2011); + DSTROY(FOOD); + PROP[BEAR]=1; + FIXED[AXE]=0; + PROP[AXE]=0; + SPK=168; + return(2011); + +L9215: if(OBJ != OGRE) goto L9216; + if(HERE(FOOD))SPK=202; + return(2011); + +L9216: SPK=14; + return(2011); +} + +/* FILL. BOTTLE OR URN MUST BE EMPTY, AND LIQUID AVAILABLE. (VASE IS NASTY.) */ + +fill() { + if(OBJ == VASE) goto L9222; + if(OBJ == URN) goto L9224; + if(OBJ != 0 && OBJ != BOTTLE) return(2011); + if(OBJ == 0 && !HERE(BOTTLE)) return(8000); + SPK=107; + if(LIQLOC(LOC) == 0)SPK=106; + if(HERE(URN) && PROP[URN] != 0)SPK=214; + if(LIQ(0) != 0)SPK=105; + if(SPK != 107) return(2011); + PROP[BOTTLE]=MOD(COND[LOC],4)/2*2; + K=LIQ(0); + if(TOTING(BOTTLE))PLACE[K]= -1; + if(K == OIL)SPK=108; + return(2011); + +L9222: SPK=29; + if(LIQLOC(LOC) == 0)SPK=144; + if(LIQLOC(LOC) == 0 || !TOTING(VASE)) return(2011); + RSPEAK(145); + PROP[VASE]=2; + FIXED[VASE]= -1; + return(discard(TRUE)); + +L9224: SPK=213; + if(PROP[URN] != 0) return(2011); + SPK=144; + K=LIQ(0); + if(K == 0 || !HERE(BOTTLE)) return(2011); + PLACE[K]=0; + PROP[BOTTLE]=1; + if(K == OIL)PROP[URN]=1; + SPK=211+PROP[URN]; + return(2011); +} diff --git a/adventure.text b/adventure.text new file mode 100644 index 0000000..5ec4034 --- /dev/null +++ b/adventure.text @@ -0,0 +1,2295 @@ +1 +1 You are standing at the end of a road before a small brick building. +1 Around you is a forest. A small stream flows out of the building and +1 down a gully. +2 You have walked up a hill, still in the forest. The road slopes back +2 down the other side of the hill. There is a building in the distance. +3 You are inside a building, a well house for a large spring. +4 You are in a valley in the forest beside a stream tumbling along a +4 rocky bed. +5 The road, which approaches from the east, ends here amid the trees. +6 The forest thins out here to reveal a steep cliff. There is no way +6 down, but a small ledge can be seen to the west across the chasm. +7 At your feet all the water of the stream splashes into a 2-inch slit +7 in the rock. Downstream the streambed is bare rock. +8 You are in a 20-foot depression floored with bare dirt. Set into the +8 dirt is a strong steel grate mounted in concrete. A dry streambed +8 leads into the depression. +9 You are in a small chamber beneath a 3x3 steel grate to the surface. +9 A low crawl over cobbles leads inward to the west. +10 You are crawling over cobbles in a low passage. There is a dim light +10 at the east end of the passage. +11 You are in a debris room filled with stuff washed in from the surface. +11 A low wide passage with cobbles becomes plugged with mud and debris +11 here, but an awkward canyon leads upward and west. In the mud someone +11 has scrawled, "MAGIC WORD XYZZY". +12 You are in an awkward sloping east/west canyon. +13 You are in a splendid chamber thirty feet high. The walls are frozen +13 rivers of orange stone. An awkward canyon and a good passage exit +13 from east and west sides of the chamber. +14 At your feet is a small pit breathing traces of white mist. An east +14 passage ends here except for a small crack leading on. +15 You are at one end of a vast hall stretching forward out of sight to +15 the west. There are openings to either side. Nearby, a wide stone +15 staircase leads downward. The hall is filled with wisps of white mist +15 swaying to and fro almost as if alive. A cold wind blows up the +15 staircase. There is a passage at the top of a dome behind you. +16 The crack is far too small for you to follow. At its widest it is +16 barely wide enough to admit your foot. +17 You are on the east bank of a fissure slicing clear across the hall. +17 The mist is quite thick here, and the fissure is too wide to jump. +18 This is a low room with a crude note on the wall. The note says, +18 "You won't get it up the steps". +19 You are in the Hall of the Mountain King, with passages off in all +19 directions. +20 You are at the bottom of the pit with a broken neck. +21 You didn't make it. +22 The dome is unclimbable. +23 You are at the west end of the Twopit Room. There is a large hole in +23 the wall above the pit at this end of the room. +24 You are at the bottom of the eastern pit in the Twopit Room. There is +24 a small pool of oil in one corner of the pit. +25 You are at the bottom of the western pit in the Twopit Room. There is +25 a large hole in the wall about 25 feet above you. +26 You clamber up the plant and scurry through the hole at the top. +27 You are on the west side of the fissure in the Hall of Mists. +28 You are in a low n/s passage at a hole in the floor. The hole goes +28 down to an e/w passage. +29 You are in the south side chamber. +30 You are in the west side chamber of the Hall of the Mountain King. +30 A passage continues west and up here. +31 %! +32 You can't get by the snake. +33 You are in a large room, with a passage to the south, a passage to the +33 west, and a wall of broken rock to the east. There is a large "Y2" on +33 a rock in the room's center. +34 You are in a jumble of rock, with cracks everywhere. +35 You're at a low window overlooking a huge pit, which extends up out of +35 sight. A floor is indistinctly visible over 50 feet below. Traces of +35 white mist cover the floor of the pit, becoming thicker to the right. +35 Marks in the dust around the window would seem to indicate that +35 someone has been here recently. Directly across the pit from you and +35 25 feet away there is a similar window looking into a lighted room. A +35 shadowy figure can be seen there peering back at you. +36 You are in a dirty broken passage. To the east is a crawl. To the +36 west is a large passage. Above you is a hole to another passage. +37 You are on the brink of a small clean climbable pit. A crawl leads +37 west. +38 You are in the bottom of a small pit with a little stream, which +38 enters and exits through tiny slits. +39 You are in a large room full of dusty rocks. There is a big hole in +39 the floor. There are cracks everywhere, and a passage leading east. +40 You have crawled through a very low wide passage parallel to and north +40 of the Hall of Mists. +41 You are at the west end of the Hall of Mists. A low wide crawl +41 continues west and another goes north. To the south is a little +41 passage 6 feet off the floor. +42 You are in a maze of twisty little passages, all alike. +43 You are in a maze of twisty little passages, all alike. +44 You are in a maze of twisty little passages, all alike. +45 You are in a maze of twisty little passages, all alike. +46 Dead end +47 Dead end +48 Dead end +49 You are in a maze of twisty little passages, all alike. +50 You are in a maze of twisty little passages, all alike. +51 You are in a maze of twisty little passages, all alike. +52 You are in a maze of twisty little passages, all alike. +53 You are in a maze of twisty little passages, all alike. +54 Dead end +55 You are in a maze of twisty little passages, all alike. +56 Dead end +57 You are on the brink of a thirty foot pit with a massive orange column +57 down one wall. You could climb down here but you could not get back +57 up. The maze continues at this level. +58 Dead end +59 You have crawled through a very low wide passage parallel to and north +59 of the Hall of Mists. +60 You are at the east end of a very long hall apparently without side +60 chambers. To the east a low wide crawl slants up. To the north a +60 round two foot hole slants down. +61 You are at the west end of a very long featureless hall. The hall +61 joins up with a narrow north/south passage. +62 You are at a crossover of a high n/s passage and a low e/w one. +63 Dead end +64 You are at a complex junction. A low hands and knees passage from the +64 north joins a higher crawl from the east to make a walking passage +64 going west. There is also a large room above. The air is damp here. +65 You are in Bedquilt, a long east/west passage with holes everywhere. +65 To explore at random select north, south, up, or down. +66 You are in a room whose walls resemble swiss cheese. Obvious passages +66 go west, east, ne, and nw. Part of the room is occupied by a large +66 bedrock block. +67 You are at the east end of the Twopit Room. The floor here is +67 littered with thin rock slabs, which make it easy to descend the pits. +67 There is a path here bypassing the pits to connect passages from east +67 and west. There are holes all over, but the only big one is on the +67 wall directly over the west pit where you can't get to it. +68 You are in a large low circular chamber whose floor is an immense slab +68 fallen from the ceiling (Slab Room). East and west there once were +68 large passages, but they are now filled with boulders. Low small +68 passages go north and south, and the south one quickly bends west +68 around the boulders. +69 You are in a secret n/s canyon above a large room. +70 You are in a secret n/s canyon above a sizable passage. +71 You are in a secret canyon at a junction of three canyons, bearing +71 north, south, and se. The north one is as tall as the other two +71 combined. +72 You are in a large low room. Crawls lead north, se, and sw. +73 Dead end crawl. +74 You are in a secret canyon which here runs e/w. It crosses over a +74 very tight canyon 15 feet below. If you go down you may not be able +74 to get back up. +75 You are at a wide place in a very tight n/s canyon. +76 The canyon here becomes too tight to go further south. +77 You are in a tall e/w canyon. A low tight crawl goes 3 feet north and +77 seems to open up. +78 The canyon runs into a mass of boulders -- dead end. +79 The stream flows out through a pair of 1 foot diameter sewer pipes. +79 It would be advisable to use the exit. +80 You are in a maze of twisty little passages, all alike. +81 Dead end +82 Dead end +83 You are in a maze of twisty little passages, all alike. +84 You are in a maze of twisty little passages, all alike. +85 Dead end +86 Dead end +87 You are in a maze of twisty little passages, all alike. +88 You are in a long, narrow corridor stretching out of sight to the +88 west. At the eastern end is a hole through which you can see a +88 profusion of leaves. +89 There is nothing here to climb. Use "up" or "out" to leave the pit. +90 You have climbed up the plant and out of the pit. +91 You are at the top of a steep incline above a large room. You could +91 climb down here, but you would not be able to climb up. There is a +91 passage leading back to the north. +92 You are in the Giant Room. The ceiling here is too high up for your +92 lamp to show it. Cavernous passages lead east, north, and south. On +92 the west wall is scrawled the inscription, "FEE FIE FOE FOO" [sic]. +93 The passage here is blocked by a recent cave-in. +94 You are at one end of an immense north/south passage. +95 You are in a magnificent cavern with a rushing stream, which cascades +95 over a sparkling waterfall into a roaring whirlpool which disappears +95 through a hole in the floor. Passages exit to the south and west. +96 You are in the Soft Room. The walls are covered with heavy curtains, +96 the floor with a thick pile carpet. Moss covers the ceiling. +97 This is the Oriental Room. Ancient oriental cave drawings cover the +97 walls. A gently sloping passage leads upward to the north, another +97 passage leads se, and a hands and knees crawl leads west. +98 You are following a wide path around the outer edge of a large cavern. +98 Far below, through a heavy white mist, strange splashing noises can be +98 heard. The mist rises up through a fissure in the ceiling. The path +98 exits to the south and west. +99 You are in an alcove. A small nw path seems to widen after a short +99 distance. An extremely tight tunnel leads east. It looks like a very +99 tight squeeze. An eerie light can be seen at the other end. +100 You're in a small chamber lit by an eerie green light. An extremely +100 narrow tunnel exits to the west. A dark corridor leads ne. +101 You're in the dark-room. A corridor leading south is the only exit. +102 You are in an arched hall. A coral passage once continued up and east +102 from here, but is now blocked by debris. The air smells of sea water. +103 You're in a large room carved out of sedimentary rock. The floor and +103 walls are littered with bits of shells imbedded in the stone. A +103 shallow passage proceeds downward, and a somewhat steeper one leads +103 up. A low hands and knees passage enters from the south. +104 You are in a long sloping corridor with ragged sharp walls. +105 You are in a cul-de-sac about eight feet across. +106 You are in an anteroom leading to a large passage to the east. Small +106 passages go west and up. The remnants of recent digging are evident. +106 A sign in midair here says "Cave under construction beyond this point. +106 Proceed at own risk. [Witt Construction Company]" +107 You are in a maze of twisty little passages, all different. +108 You are at Witt's End. Passages lead off in *ALL* directions. +109 You are in a north/south canyon about 25 feet across. The floor is +109 covered by white mist seeping in from the north. The walls extend +109 upward for well over 100 feet. Suspended from some unseen point far +109 above you, an enormous two-sided mirror is hanging parallel to and +109 midway between the canyon walls. (The mirror is obviously provided +109 for the use of the dwarves who, as you know, are extremely vain.) A +109 small window can be seen in either wall, some fifty feet up. +110 You're at a low window overlooking a huge pit, which extends up out of +110 sight. A floor is indistinctly visible over 50 feet below. Traces of +110 white mist cover the floor of the pit, becoming thicker to the left. +110 Marks in the dust around the window would seem to indicate that +110 someone has been here recently. Directly across the pit from you and +110 25 feet away there is a similar window looking into a lighted room. A +110 shadowy figure can be seen there peering back at you. +111 A large stalactite extends from the roof and almost reaches the floor +111 below. You could climb down it, and jump from it to the floor, but +111 having done so you would be unable to reach it to climb back up. +112 You are in a little maze of twisting passages, all different. +113 You are at the edge of a large underground reservoir. An opaque cloud +113 of white mist fills the room and rises rapidly upward. The lake is +113 fed by a stream, which tumbles out of a hole in the wall about 10 feet +113 overhead and splashes noisily into the water somewhere within the +113 mist. There is a passage going back toward the south. +114 Dead end +115 You are at the northeast end of an immense room, even larger than the +115 Giant Room. It appears to be a repository for the "Adventure" +115 program. Massive torches far overhead bathe the room with smoky +115 yellow light. Scattered about you can be seen a pile of bottles (all +115 of them empty), a nursery of young beanstalks murmuring quietly, a bed +115 of oysters, a bundle of black rods with rusty stars on their ends, and +115 a collection of brass lanterns. Off to one side a great many dwarves +115 are sleeping on the floor, snoring loudly. A notice nearby reads: "Do +115 not disturb the dwarves!" An immense mirror is hanging against one +115 wall, and stretches to the other end of the room, where various other +115 sundry objects can be glimpsed dimly in the distance. +116 You are at the southwest end of the repository. To one side is a pit +116 full of fierce green snakes. On the other side is a row of small +116 wicker cages, each of which contains a little sulking bird. In one +116 corner is a bundle of black rods with rusty marks on their ends. A +116 large number of velvet pillows are scattered about on the floor. A +116 vast mirror stretches off to the northeast. At your feet is a large +116 steel grate, next to which is a sign that reads, "Treasure Vault. +116 Keys in main office." +117 You are on one side of a large, deep chasm. A heavy white mist rising +117 up from below obscures all view of the far side. A sw path leads away +117 from the chasm into a winding corridor. +118 You are in a long winding corridor sloping out of sight in both +118 directions. +119 You are in a secret canyon which exits to the north and east. +120 You are in a secret canyon which exits to the north and east. +121 You are in a secret canyon which exits to the north and east. +122 You are on the far side of the chasm. A ne path leads away from the +122 chasm on this side. +123 You're in a long east/west corridor. A faint rumbling noise can be +123 heard in the distance. +124 The path forks here. The left fork leads northeast. A dull rumbling +124 seems to get louder in that direction. The right fork leads southeast +124 down a gentle slope. The main corridor enters from the west. +125 The walls are quite warm here. From the north can be heard a steady +125 roar, so loud that the entire cave seems to be trembling. Another +125 passage leads south, and a low crawl goes east. +126 You are on the edge of a breath-taking view. Far below you is an +126 active volcano, from which great gouts of molten lava come surging +126 out, cascading back down into the depths. The glowing rock fills the +126 farthest reaches of the cavern with a blood-red glare, giving every- +126 thing an eerie, macabre appearance. The air is filled with flickering +126 sparks of ash and a heavy smell of brimstone. The walls are hot to +126 the touch, and the thundering of the volcano drowns out all other +126 sounds. Embedded in the jagged roof far overhead are myriad twisted +126 formations composed of pure white alabaster, which scatter the murky +126 light into sinister apparitions upon the walls. To one side is a deep +126 gorge, filled with a bizarre chaos of tortured rock which seems to +126 have been crafted by the devil himself. An immense river of fire +126 crashes out from the depths of the volcano, burns its way through the +126 gorge, and plummets into a bottomless pit far off to your left. To +126 the right, an immense geyser of blistering steam erupts continuously +126 from a barren island in the center of a sulfurous lake, which bubbles +126 ominously. The far right wall is aflame with an incandescence of its +126 own, which lends an additional infernal splendor to the already +126 hellish scene. A dark, foreboding passage exits to the south. +127 You are in a small chamber filled with large boulders. The walls are +127 very warm, causing the air in the room to be almost stifling from the +127 heat. The only exit is a crawl heading west, through which is coming +127 a low rumbling. +128 You are walking along a gently sloping north/south passage lined with +128 oddly shaped limestone formations. +129 You are standing at the entrance to a large, barren room. A notice +129 above the entrance reads: "Caution! Bear in room!" +130 You are inside a barren room. The center of the room is completely +130 empty except for some dust. Marks in the dust lead away toward the +130 far end of the room. The only exit is the way you came in. +131 You are in a maze of twisting little passages, all different. +132 You are in a little maze of twisty passages, all different. +133 You are in a twisting maze of little passages, all different. +134 You are in a twisting little maze of passages, all different. +135 You are in a twisty little maze of passages, all different. +136 You are in a twisty maze of little passages, all different. +137 You are in a little twisty maze of passages, all different. +138 You are in a maze of little twisting passages, all different. +139 You are in a maze of little twisty passages, all different. +140 Dead end +141 You are in a long, rough-hewn, north/south corridor. +142 There is no way to go that direction. +143 You are in a large chamber with passages to the west and north. +144 You are in the ogre's storeroom. The only exit is to the south. +145 You are wandering aimlessly through the forest. +146 You are wandering aimlessly through the forest. +147 You are wandering aimlessly through the forest. +148 You are wandering aimlessly through the forest. +149 You are wandering aimlessly through the forest. +150 You are wandering aimlessly through the forest. +151 You are wandering aimlessly through the forest. +152 You are wandering aimlessly through the forest. +153 You are wandering aimlessly through the forest. +154 You are wandering aimlessly through the forest. +155 You are wandering aimlessly through the forest. +156 You are wandering aimlessly through the forest. +157 You are wandering aimlessly through the forest. +158 You are wandering aimlessly through the forest. +159 You are wandering aimlessly through the forest. +160 You are wandering aimlessly through the forest. +161 You are wandering aimlessly through the forest. +162 You are wandering aimlessly through the forest. +163 You are wandering aimlessly through the forest. +164 You are wandering aimlessly through the forest. +165 You are wandering aimlessly through the forest. +166 You are wandering aimlessly through the forest. +167 You are on a small ledge on one face of a sheer cliff. There are no +167 paths away from the ledge. Across the chasm is a small clearing +167 surrounded by forest. +168 You are walking across the bottom of the reservoir. Walls of water +168 rear up on either side. The roar of the water cascading past is +168 nearly deafening, and the mist is so thick you can barely see. +169 You are at the northern edge of the reservoir. A northwest passage +169 leads sharply up from here. +170 You are scrambling along a treacherously steep, rocky passage. +171 You are on a very steep incline, which widens at it goes upward. +172 You are at the base of a nearly vertical cliff. There are some +172 slim footholds which would enable you to climb up, but it looks +172 extremely dangerous. Here at the base of the cliff lie the remains +172 of several earlier adventurers who apparently failed to make it. +173 You are climbing along a nearly vertical cliff. +174 Just as you reach the top, your foot slips on a loose rock and you +174 tumble several hundred feet to join the other unlucky adventurers. +175 Just as you reach the top, your foot slips on a loose rock and you +175 make one last desperate grab. Your luck holds, as does your grip. +175 With an enormous heave, you lift yourself to the ledge above. +176 You are on a small ledge at the top of a nearly vertical cliff. +176 There is a low crawl leading off to the northeast. +177 You have reached a dead end. +178 There is now one more gruesome aspect to the spectacular vista. +179 >>Foof!<< +180 >>Foof!<< +181 >>Foof!<< +182 >>Foof!<< +183 >>Foof!<< +184 >>Foof!<< +-1 +2 +1 You're in front of building. +2 You're at hill in road. +3 You're inside building. +4 You're in valley. +5 You're at end of road. +6 You're at cliff. +7 You're at slit in streambed. +8 You're outside grate. +9 You're below the grate. +10 You're in cobble crawl. +11 You're in debris room. +13 You're in bird chamber. +14 You're at top of small pit. +15 You're in Hall of Mists. +17 You're on east bank of fissure. +18 You're in nugget-of-gold room. +19 You're in Hall of Mt King. +23 You're at west end of Twopit Room. +24 You're in east pit. +25 You're in west pit. +27 You're on west bank of fissure. +28 You're in n/s passage above e/w passage. +30 You're in the west side chamber. +33 You're at "Y2". +35 You're at window on pit. +36 You're in dirty passage. +37 You're at brink of small pit. +38 You're at bottom of pit with stream. +39 You're in dusty rock room. +41 You're at west end of Hall of Mists. +57 You're at brink of pit. +60 You're at east end of long hall. +61 You're at west end of long hall. +64 You're at complex junction. +65 You're in Bedquilt. +66 You're in Swiss Cheese Room. +67 You're at east end of Twopit Room. +68 You're in Slab Room. +71 You're at junction of three secret canyons. +72 You're in large low room. +74 You're in secret e/w canyon above tight canyon. +88 You're in narrow corridor. +91 You're at steep incline above large room. +92 You're in Giant Room. +95 You're in cavern with waterfall. +96 You're in Soft Room. +97 You're in Oriental Room. +98 You're in misty cavern. +99 You're in alcove. +100 You're in Plover Room. +101 You're in dark-room. +102 You're in arched hall. +103 You're in Shell Room. +106 You're in anteroom. +108 You're at Witt's End. +109 You're in Mirror Canyon. +110 You're at window on pit. +111 You're at top of stalactite. +113 You're at reservoir. +115 You're at ne end. +116 You're at sw end. +117 You're on sw side of chasm. +118 You're in sloping corridor. +122 You're on ne side of chasm. +123 You're in corridor. +124 You're at fork in path. +125 You're at junction with warm walls. +126 You're at breath-taking view. +127 You're in Chamber of Boulders. +128 You're in limestone passage. +129 You're in front of Barren Room. +130 You're in Barren Room. +167 You're on ledge. +168 You're at bottom of reservoir. +169 You're north of reservoir. +172 You're at base of cliff. +176 You're at top of cliff. +-1 +3 +1 2 2 44 29 +1 3 3 12 19 43 +1 4 5 13 14 46 30 +1 145 6 45 +1 8 63 +2 1 12 43 +2 5 44 +2 164 45 +2 157 46 6 +2 580 30 +3 1 11 32 44 +3 179 62 +3 181 65 +3 79 5 14 +4 1 4 12 45 +4 150 43 6 +4 156 44 +4 7 5 46 30 +4 8 63 +4 745 14 +5 2 2 43 29 +5 1 12 +5 158 46 6 +5 159 44 +5 165 45 +6 161 46 6 +6 163 43 +6 21 39 +7 1 12 +7 4 4 45 +7 150 43 6 +7 154 44 +7 8 5 16 46 63 +7 595 60 14 30 19 3 +8 151 43 6 +8 154 46 +8 153 44 +8 1 12 +8 7 4 13 45 +8 303009 3 19 30 +8 593 3 +9 303008 11 29 +9 593 11 +9 10 17 18 19 44 +9 14 31 +9 11 51 +10 9 11 20 21 43 +10 11 19 22 44 51 +10 14 31 +11 303008 63 +11 9 64 +11 10 17 18 23 24 43 +11 12 25 19 29 44 +11 180 62 +11 14 31 +12 303008 63 +12 9 64 +12 11 30 43 51 +12 13 19 29 44 +12 14 31 +13 303008 63 +13 9 64 +13 11 51 +13 12 25 43 +13 14 23 31 44 +14 303008 63 +14 9 64 +14 11 51 +14 13 23 43 +14 150020 30 31 34 +14 15 30 +14 16 33 44 +15 18 36 46 +15 17 7 38 44 +15 19 10 30 45 +15 150022 29 31 34 35 23 43 +15 14 29 +15 34 55 +16 14 1 +17 15 38 43 +17 312596 39 +17 412021 7 +17 412597 41 42 44 69 +17 27 41 +18 15 38 11 45 +19 15 10 29 43 +19 311028 45 37 +19 311029 46 36 +19 311030 44 7 +19 32 45 +19 35074 49 +19 211032 49 +19 74 66 +20 0 1 +21 0 1 +22 15 1 +23 67 43 42 +23 68 44 61 +23 25 30 31 +23 648 52 +24 67 29 11 +25 23 29 11 +25 524031 56 +25 26 56 +26 88 1 +27 312596 39 +27 412021 7 +27 412597 41 42 43 69 +27 17 41 +27 40 45 +27 41 44 +28 19 38 11 46 +28 33 45 55 +28 36 30 52 +29 19 38 11 45 +30 19 38 11 43 +30 62 44 29 +31 424089 1 +31 90 1 +32 19 1 +33 182 65 +33 28 46 +33 34 43 53 54 +33 35 44 +33 159302 71 +33 183 71 +34 33 30 55 +34 15 29 +35 33 43 55 +35 20 39 +36 37 43 17 +36 28 29 52 +36 39 44 +36 65 70 +37 36 44 17 +37 38 30 31 56 +38 37 56 29 11 +38 595 60 14 30 4 5 3 19 +39 36 43 23 +39 64 30 52 58 +39 65 70 +40 41 1 +41 42 46 29 23 56 +41 27 43 +41 59 45 +41 60 44 17 +42 41 29 +42 42 45 +42 43 43 +42 45 46 +42 80 44 +43 42 44 +43 44 46 +43 45 43 +44 43 43 +44 48 30 +44 50 46 +44 82 45 +45 42 44 +45 43 45 +45 46 43 +45 47 46 +45 87 29 30 +46 45 44 11 +47 45 43 11 +48 44 29 11 +49 50 43 +49 51 44 +50 44 43 +50 49 44 +50 51 30 +50 52 46 +51 49 44 +51 50 29 +51 52 43 +51 53 46 +52 50 44 +52 51 43 +52 52 46 +52 53 29 +52 55 45 +52 86 30 +53 51 44 +53 52 45 +53 54 46 +54 53 44 11 +55 52 44 +55 55 45 +55 56 30 +55 57 43 +56 55 29 11 +57 13 30 56 +57 55 44 +57 58 46 +57 83 45 +57 84 43 +58 57 43 11 +59 27 1 +60 41 43 29 17 +60 61 44 +60 62 45 30 52 +61 60 43 +61 62 45 +61 100107 46 +62 60 44 +62 63 45 +62 30 43 +62 61 46 +63 62 46 11 +64 39 29 56 59 +64 65 44 70 +64 103 45 74 +64 106 43 +65 64 43 +65 66 44 +65 65556 46 +65 68 61 +65 60556 29 +65 70070 29 +65 39 29 +65 50556 45 +65 75072 45 +65 71 45 +65 65556 30 +65 106 30 +66 65 47 +66 67 44 +66 80556 46 +66 77 25 +66 96 43 +66 50556 50 +66 97 72 +67 66 43 +67 23 44 42 +67 24 30 31 +68 23 46 +68 69 29 56 +68 65 45 +69 68 30 61 +69 331120 46 +69 119 46 +69 109 45 +69 113 75 +70 71 45 +70 65 30 23 +70 111 46 +71 65 48 +71 70 46 +71 110 45 +72 65 70 +72 118 49 +72 73 45 +72 97 48 72 +73 72 46 17 11 +74 19 43 +74 331120 44 +74 121 44 +74 75 30 +75 76 46 +75 77 45 +76 75 45 +77 75 43 +77 78 44 +77 66 45 17 +78 77 46 +79 3 1 +80 42 45 +80 80 44 +80 80 46 +80 81 43 +81 80 44 11 +82 44 46 11 +83 57 46 +83 84 43 +83 85 44 +84 57 45 +84 83 44 +84 114 50 +85 83 43 11 +86 52 29 11 +87 45 29 30 +88 25 30 56 43 +88 20 39 +88 92 44 27 +89 25 1 +90 23 1 +91 95 45 73 23 +91 72 30 56 +92 88 46 +92 93 43 +92 94 45 +93 92 46 27 11 +94 92 46 27 23 +94 309095 45 3 73 +94 611 45 +95 94 46 11 +95 92 27 +95 91 44 +96 66 44 11 +97 66 48 +97 72 44 17 +97 98 29 45 73 +98 97 46 72 +98 99 44 +99 98 50 73 +99 301 43 23 +99 100 43 +100 301 44 23 11 +100 99 44 +100 159302 71 +100 184 71 +100 101 47 22 +101 100 46 71 11 +102 103 30 74 11 +103 102 29 38 +103 104 30 +103 114618 46 +103 115619 46 +103 64 46 +104 103 29 74 +104 105 30 +105 104 29 11 +105 103 74 +106 64 29 +106 65 44 +106 108 43 +107 131 46 +107 132 49 +107 133 47 +107 134 48 +107 135 29 +107 136 50 +107 137 43 +107 138 44 +107 139 45 +107 61 30 +108 95556 43 45 46 47 48 49 50 29 30 +108 106 43 +108 626 44 +109 69 46 +109 113 45 75 +110 71 44 +110 20 39 +111 70 45 +111 40050 30 39 56 +111 50053 30 +111 45 30 +112 131 49 +112 132 45 +112 133 43 +112 134 50 +112 135 48 +112 136 47 +112 137 44 +112 138 30 +112 139 29 +112 140 46 +113 109 46 11 +113 445552 45 42 69 +113 168 45 +114 84 48 +115 116 49 +116 115 47 +116 593 30 +117 118 49 +117 233660 41 42 69 47 +117 332661 41 +117 303 41 +117 332021 39 +117 596 39 +118 72 30 +118 117 29 +119 69 45 11 +119 653 43 7 +120 69 45 +120 74 43 +121 74 43 11 +121 653 45 7 +122 123 47 +122 233660 41 42 69 49 +122 303 41 +122 596 39 +122 124 15 +122 126 28 +122 129 40 +123 122 44 +123 124 43 15 +123 126 28 +123 129 40 +124 123 44 +124 125 47 36 +124 128 48 37 30 +124 126 28 +124 129 40 +125 124 46 15 +125 126 45 28 +125 127 43 17 +126 125 46 23 11 +126 124 15 +126 610 30 +126 178 39 +127 125 44 11 17 +127 124 15 +127 126 28 +128 124 45 29 15 +128 129 46 30 40 +128 126 28 +129 128 44 29 +129 124 15 +129 130 43 19 40 3 +129 126 28 +130 129 44 11 +130 124 15 +130 126 28 +131 107 44 +131 132 48 +131 133 50 +131 134 49 +131 135 47 +131 136 29 +131 137 30 +131 138 45 +131 139 46 +131 112 43 +132 107 50 +132 131 29 +132 133 45 +132 134 46 +132 135 44 +132 136 49 +132 137 47 +132 138 43 +132 139 30 +132 112 48 +133 107 29 +133 131 30 +133 132 44 +133 134 47 +133 135 49 +133 136 43 +133 137 45 +133 138 50 +133 139 48 +133 112 46 +134 107 47 +134 131 45 +134 132 50 +134 133 48 +134 135 43 +134 136 30 +134 137 46 +134 138 29 +134 139 44 +134 112 49 +135 107 45 +135 131 48 +135 132 30 +135 133 46 +135 134 43 +135 136 44 +135 137 49 +135 138 47 +135 139 50 +135 112 29 +136 107 43 +136 131 44 +136 132 29 +136 133 49 +136 134 30 +136 135 46 +136 137 50 +136 138 48 +136 139 47 +136 112 45 +137 107 48 +137 131 47 +137 132 46 +137 133 30 +137 134 29 +137 135 50 +137 136 45 +137 138 49 +137 139 43 +137 112 44 +138 107 30 +138 131 43 +138 132 47 +138 133 29 +138 134 44 +138 135 45 +138 136 46 +138 137 48 +138 139 49 +138 112 50 +139 107 49 +139 131 50 +139 132 43 +139 133 44 +139 134 45 +139 135 30 +139 136 48 +139 137 29 +139 138 46 +139 112 47 +140 112 45 11 +140 338141 46 +140 142 46 +141 140 45 +141 143 46 +142 140 1 +143 141 44 +143 241560 45 +143 144 45 +144 143 46 11 +145 1 43 +145 157 44 +145 146 45 +145 147 46 +146 145 43 +146 163 44 +146 147 45 +146 162 46 +147 148 43 44 +147 146 45 +147 145 46 +148 147 43 45 +148 149 44 46 +149 148 43 45 +149 151 44 +149 150 46 +150 149 43 +150 151 44 +150 4 45 +150 7 46 +151 149 43 +151 150 44 +151 8 45 +151 152 46 +152 153 43 +152 155 44 +152 166 45 +152 151 46 +153 155 43 +153 152 44 +153 154 45 +153 8 46 +154 7 43 +154 155 44 +154 153 45 +154 8 46 +155 154 43 +155 152 44 +155 166 45 +155 153 46 +156 157 43 +156 158 44 +156 166 45 +156 4 46 +157 145 43 +157 156 44 +157 164 45 +157 2 46 +158 5 43 +158 160 44 +158 159 45 +158 156 46 +159 160 43 +159 166 44 +159 5 45 +159 158 46 +160 161 43 45 +160 158 44 +160 159 46 +161 162 43 +161 160 44 46 +161 6 45 +162 163 43 +162 161 44 +162 146 45 +162 165 46 +163 146 43 +163 162 44 +163 6 45 +163 164 46 +164 2 43 +164 165 44 +164 163 45 +164 157 46 +165 164 43 +165 5 44 +165 162 45 +165 165 46 +166 152 43 +166 155 44 +166 159 45 +166 156 46 +167 21 39 +168 169 45 +168 113 46 +169 445552 46 42 69 +169 168 46 +169 170 50 29 11 +170 171 29 50 +170 169 30 48 +171 170 30 48 +171 172 29 50 +172 171 30 48 +172 173 29 56 +173 172 30 +173 146175 29 +173 174 29 +174 0 1 +175 176 1 +176 173 56 30 +176 177 47 17 +177 176 49 11 17 +178 0 1 +179 11 1 +180 3 1 +181 33 1 +182 3 1 +183 100 1 +184 33 1 +-1 +4 +2 ROAD +2 HILL +3 ENTER +4 UPSTR +5 DOWNS +6 FORES +7 FORWA +7 CONTI +7 ONWAR +8 BACK +8 RETUR +8 RETRE +9 VALLE +10 STAIR +11 OUT +11 OUTSI +11 EXIT +11 LEAVE +12 BUILD +12 HOUSE +13 GULLY +14 STREA +15 FORK +16 BED +17 CRAWL +18 COBBL +19 INWAR +19 INSID +19 IN +20 SURFA +21 NULL +21 NOWHE +22 DARK +23 PASSA +23 TUNNE +24 LOW +25 CANYO +26 AWKWA +27 GIANT +28 VIEW +29 UPWAR +29 UP +29 U +29 ABOVE +29 ASCEN +30 D +30 DOWNW +30 DOWN +30 DESCE +31 PIT +32 OUTDO +33 CRACK +34 STEPS +35 DOME +36 LEFT +37 RIGHT +38 HALL +39 JUMP +40 BARRE +41 OVER +42 ACROS +43 EAST +43 E +44 WEST +44 W +45 NORTH +45 N +46 SOUTH +46 S +47 NE +48 SE +49 SW +50 NW +51 DEBRI +52 HOLE +53 WALL +54 BROKE +55 Y2 +56 CLIMB +57 LOOK +57 EXAMI +57 TOUCH +57 DESCR +58 FLOOR +59 ROOM +60 SLIT +61 SLAB +61 SLABR +62 XYZZY +63 DEPRE +64 ENTRA +65 PLUGH +66 SECRE +67 CAVE +69 CROSS +70 BEDQU +71 PLOVE +72 ORIEN +73 CAVER +74 SHELL +75 RESER +76 MAIN +76 OFFIC +1001 KEYS +1001 KEY +1002 LAMP +1002 LANTE +1003 GRATE +1004 CAGE +1005 ROD +1006 ROD (MUST BE NEXT OBJECT AFTER "REAL" ROD) +1007 STEPS +1008 BIRD +1009 DOOR +1010 PILLO +1010 VELVE +1011 SNAKE +1012 FISSU +1013 TABLE +1014 CLAM +1015 OYSTE +1016 MAGAZ +1016 ISSUE +1016 SPELU +1016 "SPEL +1017 DWARF +1017 DWARV +1018 KNIFE +1018 KNIVE +1019 FOOD +1019 RATIO +1020 BOTTL +1020 JAR +1021 WATER +1021 H2O +1022 OIL +1023 MIRRO +1024 PLANT +1024 BEANS +1025 PLANT (MUST BE NEXT OBJECT AFTER "REAL" PLANT) +1026 STALA +1027 SHADO +1027 FIGUR +1027 WINDO (SAME AS FIGURE) +1028 AXE +1029 DRAWI +1030 PIRAT +1030 GENIE +1030 DJINN +1031 DRAGO +1032 CHASM +1033 TROLL +1034 TROLL (MUST BE NEXT OBJECT AFTER "REAL" TROLL) +1035 BEAR +1036 MESSA +1037 VOLCA +1037 GEYSE (SAME AS VOLCANO) +1038 MACHI +1038 VENDI +1039 BATTE +1040 CARPE +1040 MOSS +1040 CURTA (SAME AS CARPET) +1041 OGRE +1042 URN +1043 CAVIT +1044 BLOOD +1045 RESER (VERB OVERRIDES) +1046 APPEN +1046 LEPOR +1047 MUD +1048 NOTE +1049 SIGN +1050 GOLD +1050 NUGGE +1051 DIAMO +1052 SILVE +1052 BARS +1053 JEWEL +1054 COINS +1055 CHEST +1055 BOX +1055 TREAS +1056 EGGS +1056 EGG +1056 NEST +1057 TRIDE +1058 VASE +1058 MING +1058 SHARD +1058 POTTE +1059 EMERA +1060 PLATI +1060 PYRAM +1061 PEARL +1062 RUG +1062 PERSI +1063 SPICE +1064 CHAIN +1065 RUBY +1066 JADE +1066 NECKL +1067 AMBER +1067 GEMST +1068 SAPPH +1069 EBONY +1069 STATU +2001 CARRY +2001 TAKE +2001 KEEP +2001 CATCH +2001 STEAL +2001 CAPTU +2001 GET +2001 TOTE +2001 SNARF +2002 DROP +2002 RELEA +2002 FREE +2002 DISCA +2002 DUMP +2003 SAY +2003 CHANT +2003 SING +2003 UTTER +2003 MUMBL +2004 UNLOC +2004 OPEN +2005 NOTHI +2006 LOCK +2006 CLOSE +2007 LIGHT +2007 ON +2008 EXTIN +2008 OFF +2009 WAVE +2009 SHAKE +2009 SWING +2010 CALM +2010 PLACA +2010 TAME +2011 WALK +2011 RUN +2011 TRAVE +2011 GO +2011 PROCE +2011 CONTI +2011 EXPLO +2011 FOLLO +2011 TURN +2012 ATTAC +2012 KILL +2012 FIGHT +2012 HIT +2012 STRIK +2012 SLAY +2013 POUR +2014 EAT +2014 DEVOU +2015 DRINK +2016 RUB +2017 THROW +2017 TOSS +2018 QUIT +2019 FIND +2019 WHERE +2020 INVEN +2021 FEED +2022 FILL +2023 BLAST +2023 DETON +2023 IGNIT +2023 BLOWU +2024 SCORE +2025 FEE +2025 FIE +2025 FOE +2025 FOO +2025 FUM +2026 BRIEF +2027 READ +2027 PERUS +2028 BREAK +2028 SHATT +2028 SMASH +2029 WAKE +2029 DISTU +2030 SUSPE +2030 PAUSE +2030 SAVE +2031 RESUM +2031 RESTA +2032 FLY +2033 LISTE +2034 Z'ZZZ (GETS REPLACED) +3001 FEE +3002 FIE +3003 FOE +3004 FOO +3005 FUM +3013 THANK +3050 SESAM +3050 OPENS +3050 ABRA +3050 ABRAC +3050 SHAZA +3050 HOCUS +3050 POCUS +3051 HELP +3051 ? +3054 NO +3064 TREE +3064 TREES +3066 DIG +3066 EXCAV +3068 LOST +3069 MIST +3079 FUCK +3139 STOP +3142 INFO +3142 INFOR +3147 SWIM +3246 WIZAR +3271 YES +3275 NEWS +-1 +5 +1 Set of keys +000 There are some keys on the ground here. +2 Brass lantern +000 There is a shiny brass lamp nearby. +100 There is a lamp shining nearby. +3 *grate +000 The grate is locked. +100 The grate is open. +4 Wicker cage +000 There is a small wicker cage discarded nearby. +5 Black rod +000 A three foot black rod with a rusty star on an end lies nearby. +6 Black rod +000 A three foot black rod with a rusty mark on an end lies nearby. +7 *steps +000 Rough stone steps lead down the pit. +100 Rough stone steps lead up the dome. +8 Little bird in cage +000 A cheerful little bird is sitting here singing. +100 There is a little bird in the cage. +200 A cheerful little bird is sitting here singing. +300 The bird's singing is quite melodious. +400 The bird does not seem inclined to sing while in the cage. +500 It almost seems as though the bird is trying to tell you something. +600 To your surprise, you can understand the bird's chirping; it is +600 singing about the joys of its forest home. +700 The bird does not seem inclined to sing while in the cage. +800 The bird is singing to you in gratitude for your having returned it to +800 its home. In return, it informs you of a magic word which it thinks +800 you may find useful somewhere near the Hall of Mists. The magic word +800 changes frequently, but for now the bird believes it is "%W". You +800 thank the bird for this information, and it flies off into the forest. +9 *rusty door +000 The way north is barred by a massive, rusty, iron door. +100 The way north leads through a massive, rusty, iron door. +10 Velvet pillow +000 A small velvet pillow lies on the floor. +11 *snake +000 A huge green fierce snake bars the way! +100 %! (chased away) +200 The snake is hissing venomously. +12 *fissure +000 %! +100 A crystal bridge now spans the fissure. +200 The crystal bridge has vanished! +13 *stone tablet +000 A massive stone tablet imbedded in the wall reads: +000 "Congratulations on bringing light into the dark-room!" +100 "Congratulations on bringing light into the dark-room!" +14 Giant clam >GRUNT!< +000 There is an enormous clam here with its shell tightly closed. +100 The clam is as tight-mouthed as a, er, clam. +15 Giant oyster >GROAN!< +000 There is an enormous oyster here with its shell tightly closed. +100 Interesting. There seems to be something written on the underside of +100 the oyster. +200 Even though it's an oyster, the critter's as tight-mouthed as a clam. +300 It says the same thing it did before. Hm, maybe it's a pun? +16 "Spelunker Today" +000 There are a few recent issues of "Spelunker Today" magazine here. +100 I'm afraid the magazine is written in dwarvish. But pencilled on one +100 cover you see, "Please leave the magazines at the construction site." +19 Tasty food +000 There is food here. +20 Small bottle +000 There is a bottle of water here. +100 There is an empty bottle here. +200 There is a bottle of oil here. +21 Water in the bottle +22 Oil in the bottle +23 *mirror +000 %! +24 *plant +000 There is a tiny little plant in the pit, murmuring "water, water, ..." +100 There is a 12-foot-tall beanstalk stretching up out of the pit, +100 bellowing "WATER!! WATER!!" +200 There is a gigantic beanstalk stretching all the way up to the hole. +300 The plant spurts into furious growth for a few seconds. +400 The plant grows explosively, almost filling the bottom of the pit. +500 You've over-watered the plant! It's shriveling up! And now . . . +600 The plant continues to ask plaintively for water. +700 The plant continues to demand water. +800 The plant now maintains a contented silence. +25 *phony plant (seen in Twopit Room only when tall enough) +000 %! +100 The top of a 12-foot-tall beanstalk is poking out of the west pit. +200 There is a huge beanstalk growing out of the west pit up to the hole. +26 *stalactite +000 %! +27 *shadowy figure and/or window +000 The shadowy figure seems to be trying to attract your attention. +28 Dwarf's axe +000 There is a little axe here. +100 There is a little axe lying beside the bear. +29 *cave drawings +000 %! +30 *pirate/genie +000 %! (never present) +31 *dragon +000 A huge green fierce dragon bars the way! +100 The blood-specked body of a huge green dead dragon lies to one side. +200 The body of a huge green dead dragon is lying off to one side. +300 Congratulations! You have just vanquished a dragon with your bare +300 hands! (Unbelievable, isn't it?) +400 The dragon's ominous hissing does not bode well for you. +500 The dragon is, not surprisingly, silent. +600 The dragon is, not surprisingly, silent. +32 *chasm +000 A rickety wooden bridge extends across the chasm, vanishing into the +000 mist. A notice posted on the bridge reads, "Stop! Pay troll!" +100 The wreckage of a bridge (and a dead bear) can be seen at the bottom +100 of the chasm. +33 *troll +000 A burly troll stands by the bridge and insists you throw him a +000 treasure before you may cross. +100 The troll steps out from beneath the bridge and blocks your way. +200 %! (chased away) +300 The troll sounds quite adamant in his demand for a treasure. +34 *phony troll +000 The troll is nowhere to be seen. +35 %! (bear uses rtext 141) +000 There is a ferocious cave bear eying you from the far end of the room! +100 There is a gentle cave bear sitting placidly in one corner. +200 There is a contented-looking bear wandering about nearby. +300 %! (dead) +36 *message in second maze +000 There is a message scrawled in the dust in a flowery script, reading: +000 "This is not the maze where the pirate leaves his treasure chest." +100 "This is not the maze where the pirate leaves his treasure chest." +37 *volcano and/or geyser +000 %! +38 *vending machine +000 There is a massive and somewhat battered vending machine here. The +000 instructions on it read: "Drop coins here to receive fresh batteries." +100 "Drop coins here to receive fresh batteries." +200 As you strike the vending machine, it pivots backward along with a +200 section of wall, revealing a dark passage leading south. +300 There is a massive vending machine here, swung back to reveal a +300 southward passage. +400 "Drop coins here to receive fresh batteries." +500 The vending machine swings back to block the passage. +39 Batteries +000 There are fresh batteries here. +100 Some worn-out batteries have been discarded nearby. +40 *carpet and/or moss and/or curtains +000 %! +41 *ogre +000 A formidable ogre bars the northern exit. +100 The ogre is apparently the strong, silent type. +42 *urn +000 A small urn is embedded in the rock. +100 A small urn full of oil is embedded in the rock. +200 A small oil flame extrudes from an urn embedded in the rock. +43 *cavity +000 %! (something in it) +100 There is a small urn-shaped cavity in the rock. +44 *blood +000 %! (described with dragon) +45 *reservoir +000 %! +100 The waters have parted to form a narrow path across the reservoir. +200 The waters crash together again. +46 Leporine appendage +000 Your keen eye spots a severed leporine appendage lying on the ground. +47 *mud +000 %! +100 "MAGIC WORD XYZZY" +48 *note +000 %! +100 "You won't get it up the steps" +49 *sign +000 %! +100 Cave under construction beyond this point. +100 Proceed at own risk. +100 [Witt Construction Company] +200 "Treasure Vault. Keys in main office." +50 Large gold nugget +000 There is a large sparkling nugget of gold here! +51 Several diamonds +000 There are diamonds here! +52 Bars of silver +000 There are bars of silver here! +53 Precious jewelry +000 There is precious jewelry here! +54 Rare coins +000 There are many coins here! +55 Treasure chest +000 The pirate's treasure chest is here! +56 Golden eggs +000 There is a large nest here, full of golden eggs! +100 The nest of golden eggs has vanished! +200 Done! +57 Jeweled trident +000 There is a jewel-encrusted trident here! +58 Ming vase +000 There is a delicate, precious, ming vase here! +100 The vase is now resting, delicately, on a velvet pillow. +200 The floor is littered with worthless shards of pottery. +300 The ming vase drops with a delicate crash. +59 Egg-sized emerald +000 There is an emerald here the size of a plover's egg! +100 There is an emerald resting in a small cavity in the rock! +60 Platinum pyramid +000 There is a platinum pyramid here, 8 inches on a side! +61 Glistening pearl +000 Off to one side lies a glistening pearl! +62 Persian rug +000 There is a persian rug spread out on the floor! +100 The dragon is sprawled out on a persian rug!! +200 There is a persian rug here, hovering in mid-air! +63 Rare spices +000 There are rare spices here! +64 Golden chain +000 There is a golden chain lying in a heap on the floor! +100 The bear is locked to the wall with a golden chain! +200 There is a golden chain locked to the wall! +65 Giant ruby +000 There is an enormous ruby here! +100 There is a ruby resting in a small cavity in the rock! +66 Jade necklace +000 A precious jade necklace has been dropped here! +67 Amber gemstone +000 There is a rare amber gemstone here! +100 There is an amber gemstone resting in a small cavity in the rock! +68 Star sapphire +000 A brilliant blue star sapphire is here! +100 There is a star sapphire resting in a small cavity in the rock! +69 Ebony statuette +000 There is a richly-carved ebony statuette here! +-1 +6 +1 Somewhere nearby is Colossal Cave, where others have found fortunes in +1 treasure and gold, though it is rumored that some who enter are never +1 seen again. Magic is said to work in the cave. I will be your eyes +1 and hands. Direct me with commands of 1 or 2 words. I should warn +1 you that I look at only the first five letters of each word, so you'll +1 have to enter "northeast" as "ne" to distinguish it from "north". +1 You can type "help" for some general hints. For information on how +1 to end your adventure, scoring, etc., type "info". +1 - - - +1 This program was originally developed by Willie Crowther. Most of the +1 features of the current program were added by Don Woods. Contact Don +1 if you have any questions, comments, etc. +2 A little dwarf with a big knife blocks your way. +3 A little dwarf just walked around a corner, saw you, threw a little +3 axe at you which missed, cursed, and ran away. +4 There are %1 threatening little dwarves in the room with you. +5 There is a threatening little dwarf in the room with you! +6 One sharp nasty knife is thrown at you! +7 A hollow voice says "PLUGH". +8 It gets you! +9 It misses! +10 I am unsure how you are facing. Use compass points or nearby objects. +11 I don't know in from out here. Use compass points or name something +11 in the general direction you want to go. +12 I don't know how to apply that word here. +13 You're quite welcome. +14 I'm game. Would you care to explain how? +15 Sorry, but I am not allowed to give more detail. I will repeat the +15 long description of your location. +16 It is now pitch dark. If you proceed you will likely fall into a pit. +17 If you prefer, simply type w rather than west. +18 Are you trying to catch the bird? +19 Something about you seems to be frightening the bird. Perhaps you +19 might figure out what it is. +20 Are you trying to somehow deal with the snake? +21 You can't kill the snake, or drive it away, or avoid it, or anything +21 like that. There is a way to get by, but you don't have the necessary +21 resources right now. +22 Do you really want to quit now? +23 You fell into a pit and broke every bone in your body! +24 You are already carrying it! +25 You can't be serious! +26 The bird seemed unafraid at first, but as you approach it becomes +26 disturbed and you cannot catch it. +27 You can catch the bird, but you cannot carry it. +28 There is nothing here with a lock! +29 You aren't carrying it! +30 The little bird attacks the green snake, and in an astounding flurry +30 drives the snake away. +31 You have no keys! +32 It has no lock. +33 I don't know how to lock or unlock such a thing. +34 It was already locked. +35 The grate is now locked. +36 The grate is now unlocked. +37 It was already unlocked. +38 The urn is empty and will not light. +39 Your lamp is now on. +40 Your lamp is now off. +41 There is no way to get past the bear to unlock the chain, which is +41 probably just as well. +42 Nothing happens. +43 Where? +44 There is nothing here to attack. +45 The little bird is now dead. Its body disappears. +46 Attacking the snake both doesn't work and is very dangerous. +47 You killed a little dwarf. +48 You attack a little dwarf, but he dodges out of the way. +49 With what? Your bare hands? +50 Good try, but that is an old worn-out magic word. +51 I know of places, actions, and things. Most of my vocabulary +51 describes places and is used to move you there. To move, try words +51 like forest, building, downstream, enter, east, west, north, south, +51 up, or down. I know about a few special objects, like a black rod +51 hidden in the cave. These objects can be manipulated using some of +51 the action words that I know. Usually you will need to give both the +51 object and action words (in either order), but sometimes I can infer +51 the object from the verb alone. Some objects also imply verbs; in +51 particular, "inventory" implies "take inventory", which causes me to +51 give you a list of what you're carrying. Some objects have unexpected +51 effects; the effects are not always desirable! Usually people having +51 trouble moving just need to try a few more words. Usually people +51 trying unsuccessfully to manipulate an object are attempting something +51 beyond their (or my!) capabilities and should try a completely +51 different tack. One point often confusing to beginners is that, when +51 there are several ways to go in a certain direction (e.g., if there +51 are several holes in a wall), choosing that direction in effect +51 chooses one of the ways at random; often, though, by specifying the +51 place you want to reach you can guarantee choosing the right path. +51 Also, to speed the game you can sometimes move long distances with a +51 single word. For example, "building" usually gets you to the building +51 from anywhere above ground except when lost in the forest. Also, note +51 that cave passages and forest paths turn a lot, so leaving one place +51 heading north doesn't guarantee entering the next from the south. +51 However (another important point), except when you've used a "long +51 distance" word such as "building", there is always a way to go back +51 where you just came from unless I warn you to the contrary, even +51 though the direction that takes you back might not be the reverse of +51 what got you here. Good luck, and have fun! +52 There is no way to go that direction. +53 Please stick to 1- and 2-word commands. +54 OK +55 You can't unlock the keys. +56 You have crawled around in some little holes and wound up back in the +56 main passage. +57 I don't know where the cave is, but hereabouts no stream can run on +57 the surface for long. I would try the stream. +58 I need more detailed instructions to do that. +59 I can only tell you what you see as you move about and manipulate +59 things. I cannot tell you where remote things are. +60 The ogre snarls and shoves you back. +61 Huh? +62 Are you trying to get into the cave? +63 The grate is very solid and has a hardened steel lock. You cannot +63 enter without a key, and there are no keys nearby. I would recommend +63 looking elsewhere for the keys. +64 The trees of the forest are large hardwood oak and maple, with an +64 occasional grove of pine or spruce. There is quite a bit of under- +64 growth, largely birch and ash saplings plus nondescript bushes of +64 various sorts. This time of year visibility is quite restricted by +64 all the leaves, but travel is quite easy if you detour around the +64 spruce and berry bushes. +65 Welcome to Adventure!! Would you like instructions? +66 Digging without a shovel is quite impractical. Even with a shovel +66 progress is unlikely. +67 Blasting requires dynamite. +68 I'm as confused as you are. +69 Mist is a white vapor, usually water, seen from time to time in +69 caverns. It can be found anywhere but is frequently a sign of a deep +69 pit leading down to water. +70 Your feet are now wet. +71 I think I just lost my appetite. +72 Thank you, it was delicious! +73 You have taken a drink from the stream. The water tastes strongly of +73 minerals, but is not unpleasant. It is extremely cold. +74 The bottle of water is now empty. +75 Rubbing the electric lamp is not particularly rewarding. Anyway, +75 nothing exciting happens. +76 Peculiar. Nothing unexpected happens. +77 Your bottle is empty and the ground is wet. +78 You can't pour that. +79 Watch it! +80 Which way? +81 Oh dear, you seem to have gotten yourself killed. I might be able to +81 help you out, but I've never really done this before. Do you want me +81 to try to reincarnate you? +82 All right. But don't blame me if something goes wr...... +82 --- POOF!! --- +82 You are engulfed in a cloud of orange smoke. Coughing and gasping, +82 you emerge from the smoke and find.... +83 You clumsy oaf, you've done it again! I don't know how long I can +83 keep this up. Do you want me to try reincarnating you again? +84 Okay, now where did I put my orange smoke?.... >POOF!< +84 Everything disappears in a dense cloud of orange smoke. +85 Now you've really done it! I'm out of orange smoke! You don't expect +85 me to do a decent reincarnation without any orange smoke, do you? +86 Okay, if you're so smart, do it yourself! I'm leaving! +90 >>> messages 81 thru 90 are reserved for "obituaries". <<< +91 Sorry, but I no longer seem to remember how it was you got here. +92 You can't carry anything more. You'll have to drop something first. +93 You can't go through a locked steel grate! +94 I believe what you want is right here with you. +95 You don't fit through a two-inch slit! +96 I respectfully suggest you go across the bridge instead of jumping. +97 There is no way across the fissure. +98 You're not carrying anything. +99 You are currently holding the following: +100 It's not hungry (it's merely pinin' for the fjords). Besides, you +100 have no bird seed. +101 The snake has now devoured your bird. +102 There's nothing here it wants to eat (except perhaps you). +103 You fool, dwarves eat only coal! Now you've made him *REALLY* mad!! +104 You have nothing in which to carry it. +105 Your bottle is already full. +106 There is nothing here with which to fill the bottle. +107 Your bottle is now full of water. +108 Your bottle is now full of oil. +109 You can't fill that. +110 Don't be ridiculous! +111 The door is extremely rusty and refuses to open. +112 The plant indignantly shakes the oil off its leaves and asks, "Water?" +113 The hinges are quite thoroughly rusted now and won't budge. +114 The oil has freed up the hinges so that the door will now move, +114 although it requires some effort. +115 The plant has exceptionally deep roots and cannot be pulled free. +116 The dwarves' knives vanish as they strike the walls of the cave. +117 Something you're carrying won't fit through the tunnel with you. +117 You'd best take inventory and drop something. +118 You can't fit this five-foot clam through that little passage! +119 You can't fit this five-foot oyster through that little passage! +120 I advise you to put down the clam before opening it. >STRAIN!< +121 I advise you to put down the oyster before opening it. >WRENCH!< +122 You don't have anything strong enough to open the clam. +123 You don't have anything strong enough to open the oyster. +124 A glistening pearl falls out of the clam and rolls away. Goodness, +124 this must really be an oyster. (I never was very good at identifying +124 bivalves.) Whatever it is, it has now snapped shut again. +125 The oyster creaks open, revealing nothing but oyster inside. It +125 promptly snaps shut again. +126 You have crawled around in some little holes and found your way +126 blocked by a recent cave-in. You are now back in the main passage. +127 There are faint rustling noises from the darkness behind you. +128 Out from the shadows behind you pounces a bearded pirate! "Har, har," +128 he chortles, "I'll just take all this booty and hide it away with me +128 chest deep in the maze!" He snatches your treasure and vanishes into +128 the gloom. +129 A sepulchral voice reverberating through the cave, says, "Cave closing +129 soon. All adventurers exit immediately through main office." +130 A mysterious recorded voice groans into life and announces: +130 "This exit is closed. Please leave via main office." +131 It looks as though you're dead. Well, seeing as how it's so close to +131 closing time anyway, I think we'll just call it a day. +132 The sepulchral voice intones, "The cave is now closed." As the echoes +132 fade, there is a blinding flash of light (and a small puff of orange +132 smoke). . . . As your eyes refocus, you look around and find... +133 There is a loud explosion, and a twenty-foot hole appears in the far +133 wall, burying the dwarves in the rubble. You march through the hole +133 and find yourself in the main office, where a cheering band of +133 friendly elves carry the conquering adventurer off into the sunset. +134 There is a loud explosion, and a twenty-foot hole appears in the far +134 wall, burying the snakes in the rubble. A river of molten lava pours +134 in through the hole, destroying everything in its path, including you! +135 There is a loud explosion, and you are suddenly splashed across the +135 walls of the room. +136 The resulting ruckus has awakened the dwarves. There are now several +136 threatening little dwarves in the room with you! Most of them throw +136 knives at you! All of them get you! +137 Oh, leave the poor unhappy bird alone. +138 I daresay whatever you want is around here somewhere. +139 I don't know the word "stop". Use "quit" if you want to give up. +140 You can't get there from here. +141 You are being followed by a very large, tame bear. +142 For a summary of the most recent changes to the game, say "news". +142 If you want to end your adventure early, say "quit". To suspend your +142 adventure such that you can continue later, say "suspend" (or "pause" +142 or "save"). To see how well you're doing, say "score". To get full +142 credit for a treasure, you must have left it safely in the building, +142 though you get partial credit just for locating it. You lose points +142 for getting killed, or for quitting, though the former costs you more. +142 There are also points based on how much (if any) of the cave you've +142 managed to explore; in particular, there is a large bonus just for +142 getting in (to distinguish the beginners from the rest of the pack), +142 and there are other ways to determine whether you've been through some +142 of the more harrowing sections. If you think you've found all the +142 treasures, just keep exploring for a while. If nothing interesting +142 happens, you haven't found them all yet. If something interesting +142 *DOES* happen (incidentally, there *ARE* ways to hasten things along), +142 it means you're getting a bonus and have an opportunity to garner many +142 more points in the Master's section. I may occasionally offer hints +142 if you seem to be having trouble. If I do, I'll warn you in advance +142 how much it will affect your score to accept the hints. Finally, to +142 save time, you may specify "brief", which tells me never to repeat the +142 full description of a place unless you explicitly ask me to. +143 Now let's see you do it without suspending in mid-Adventure. +144 There is nothing here with which to fill it. +145 The sudden change in temperature has delicately shattered the vase. +146 It is beyond your power to do that. +147 I don't know how. +148 It is too far up for you to reach. +149 You killed a little dwarf. The body vanishes in a cloud of greasy +149 black smoke. +150 The shell is very strong and is impervious to attack. +151 What's the matter, can't you read? Now you'd best start over. +152 The axe bounces harmlessly off the dragon's thick scales. +153 The dragon looks rather nasty. You'd best not try to get by. +154 The little bird attacks the green dragon, and in an astounding flurry +154 gets burnt to a cinder. The ashes blow away. +155 On what? +156 Okay, from now on I'll only describe a place in full the first time +156 you come to it. To get the full description, say "look". +157 Trolls are close relatives with the rocks and have skin as tough as +157 that of a rhinoceros. The troll fends off your blows effortlessly. +158 The troll deftly catches the axe, examines it carefully, and tosses it +158 back, declaring, "Good workmanship, but it's not valuable enough." +159 The troll catches your treasure and scurries away out of sight. +160 The troll refuses to let you cross. +161 There is no longer any way across the chasm. +162 Just as you reach the other side, the bridge buckles beneath the +162 weight of the bear, which was still following you around. You +162 scrabble desperately for support, but as the bridge collapses you +162 stumble back and fall into the chasm. +163 The bear lumbers toward the troll, who lets out a startled shriek and +163 scurries away. The bear soon gives up the pursuit and wanders back. +164 The axe misses and lands near the bear where you can't get at it. +165 With what? Your bare hands? Against *HIS* bear hands?? +166 The bear is confused; he only wants to be your friend. +167 For crying out loud, the poor thing is already dead! +168 The bear eagerly wolfs down your food, after which he seems to calm +168 down considerably and even becomes rather friendly. +169 The bear is still chained to the wall. +170 The chain is still locked. +171 The chain is now unlocked. +172 The chain is now locked. +173 There is nothing here to which the chain can be locked. +174 There is nothing here to eat. +175 Do you want the hint? +176 Do you need help getting out of the maze? +177 You can make the passages look less alike by dropping things. +178 Are you trying to explore beyond the plover room? +179 There is a way to explore that region without having to worry about +179 falling into a pit. None of the objects available is immediately +179 useful in discovering the secret. +180 Do you need help getting out of here? +181 Don't go west. +182 Gluttony is not one of the troll's vices. Avarice, however, is. +183 Your lamp is getting dim. You'd best start wrapping this up, unless +183 you can find some fresh batteries. I seem to recall there's a vending +183 machine in the maze. Bring some coins with you. +184 Your lamp has run out of power. +185 Please answer the question. +186 There are faint rustling noises from the darkness behind you. As you +186 turn toward them, the beam of your lamp falls across a bearded pirate. +186 He is carrying a large chest. "Shiver me timbers!" he cries, "I've +186 been spotted! I'd best hie meself off to the maze to hide me chest!" +186 With that, he vanishes into the gloom. +187 Your lamp is getting dim. You'd best go back for those batteries. +188 Your lamp is getting dim. I'm taking the liberty of replacing the +188 batteries. +189 Your lamp is getting dim, and you're out of spare batteries. You'd +189 best start wrapping this up. +190 You sift your fingers through the dust, but succeed only in +190 obliterating the cryptic message. +191 Do you need help dealing with the ogre? +192 Hmmm, this looks like a clue, which means it'll cost you 10 points to +192 read it. Should I go ahead and read it anyway? +193 It says, "There is a way out of this place. Do you need any more +193 information to escape? Sorry, but this initial hint is all you get." +194 There is nothing the presence of which will prevent you from defeating +194 him; thus it can't hurt to fetch everything you possibly can. +195 I'm afraid I don't understand. +196 Your hand passes through it as though it weren't there. +197 You strike the mirror a resounding blow, whereupon it shatters into a +197 myriad tiny fragments. +198 You have taken the vase and hurled it delicately to the ground. +199 You prod the nearest dwarf, who wakes up grumpily, takes one look at +199 you, curses, and grabs for his axe. +200 Is this acceptable? +201 This adventure is already over. To start a new adventure, or to +201 resume an earlier adventure, please run a fresh copy of the program. +202 The ogre doesn't appear to be hungry. +203 The ogre, who despite his bulk is quite agile, easily dodges your +203 attack. He seems almost amused by your puny effort. +204 The ogre, distracted by your rush, is struck by the knife. With a +204 blood-curdling yell he turns and bounds after the dwarves, who flee +204 in panic. You are left alone in the room. +205 The ogre, distracted by your rush, is struck by the knife. With a +205 blood-curdling yell he turns and bounds after the dwarf, who flees +205 in panic. You are left alone in the room. +206 The bird flies about agitatedly for a moment. +207 The bird flies agitatedly about the cage. +208 The bird flies about agitatedly for a moment, then disappears through +208 the crack. It reappears shortly, carrying in its beak a jade +208 necklace, which it drops at your feet. +209 The urn is now lit. +210 The urn is now dark. +211 You empty the bottle into the urn, which promptly ejects the water +211 with uncanny accuracy, squirting you directly between the eyes. +212 Your bottle is now empty and the urn is full of oil. +213 The urn is already full of oil. +214 There's no way to get the oil out of the urn. +215 The urn is far too firmly embedded for your puny strength to budge it. +216 As you rub the urn, there is a flash of light and a genie appears. +216 His aspect is stern as he advises: "One who wouldst traffic in +216 precious stones must first learn to recognize the signals thereof." +216 He wrests the urn from the stone, leaving a small cavity. Turning to +216 face you again, he fixes you with a steely eye and intones: "Caution!" +216 Genie and urn vanish in a cloud of amber smoke. The smoke condenses +216 to form a rare amber gemstone, resting in the cavity in the rock. +217 I suppose you collect doughnut holes, too? +218 The gem fits easily into the cavity. +219 The persian rug stiffens and rises a foot or so off the ground. +220 The persian rug draped over your shoulder seems to wriggle for a +220 moment, but then subsides. +221 The persian rug settles gently to the ground. +222 The rug hovers stubbornly where it is. +223 The rug does not appear inclined to cooperate. +224 If you mean to use the persian rug, it does not appear inclined to +224 cooperate. +225 Though you flap your arms furiously, it is to no avail. +226 You board the persian rug, which promptly whisks you across the chasm. +226 You have time for a fleeting glimpse of a two thousand foot drop to a +226 mighty river; then you find yourself on the other side. +227 The rug ferries you back across the chasm. +228 All is silent. +229 The stream is gurgling placidly. +230 The wind whistles coldly past your ears. +231 The stream splashes loudly into the pool. +232 You are unable to make anything of the splashing noise. +233 You can hear the murmuring of the beanstalks and the snoring of the +233 dwarves. +234 A loud hissing emanates from the snake pit. +235 The air is filled with a dull rumbling sound. +236 The roar is quite loud here. +237 The roaring is so loud that it drowns out all other sound. +238 The bird eyes you suspiciously and flutters away. A moment later you +238 feel something wet land on your head, but upon looking up you can see +238 no sign of the culprit. +239 There are only a few drops--not enough to carry. +240 Your head buzzes strangely for a moment. +241 (Uh, y'know, that wasn't very bright.) +242 It's a pity you took so long about it. +243 Are you wondering what to do here? +244 This section is quite advanced. Find the cave first. +245 Upstream or downstream? +246 Wizards are not to be disturbed by such as you. +247 Would you like to be shown out of the forest? +248 Go east ten times. If that doesn't get you out, then go south, then +248 west twice, then south. +249 The waters are crashing loudly against the shore. +250 %1 of them throw knives at you! +251 %1 of them get you! +252 One of them gets you! +253 None of them hits you! +254 Sorry, I don't know the word "%W". +255 What do you want to do with the %L? +256 I see no %L here. +257 %C what? +258 Okay, "%W". +259 You have garnered %3 out of a possible %3 points, using %5 turn%S. +260 I can suspend your Adventure for you so that you can resume later, but +260 it will cost you 5 points. +261 I am prepared to give you a hint, but it will cost you %1 point%S. +262 You scored %3 out of a possible %3, using%5 turn%S. +263 To achieve the next higher rating, you need %2 more point%S. +264 To achieve the next higher rating would be a neat trick! +264 Congratulations!! +265 You just went off my scale!! +266 To resume your Adventure, start a new game and then say "RESUME". +267 Table space used: +267 %6 of %6 words of messages %6 of %6 travel options +267 %6 of %6 vocabulary words %6 of %6 locations +267 %6 of %6 objects %6 of %6 action verbs +267 %6 of %6 "random" messages %6 of %6 "class" messages +267 %6 of %6 hints %6 of %6 turn threshholds +268 To resume an earlier Adventure, you must abandon the current one. +269 I'm sorry, but that Adventure was begun using Version%2.%1 of the +269 program, and this is Version%2.%1. You must find the other version +269 in order to resume that Adventure. +270 A dark fog creeps in to surround you. From somewhere in the fog you +270 hear a stern voice. "This Adventure has been tampered with! You have +270 been dabbling in magic, knowing not the havoc you might cause thereby. +270 Leave at once, before you do irrevocable harm!" The fog thickens, +270 until at last you can see nothing at all. Your vision then clears, +270 and you find yourself back in The Real World. +271 Guess again. +272 You're missing only one other treasure. Do you need help finding it? +273 Once you've found all the other treasures, it is no longer possible to +273 locate the one you're now missing. +274 Sorry, but the path twisted and turned so much that I can't figure +274 out which way to go to get back. +275 Version 2.5 is essentially the same as Version II; the cave and the +275 hazards therein are unchanged, and top score is still 430 points. +275 There are a few more hints, especially for some of the more obscure +275 puzzles. There are a few minor bugfixes and cosmetic changes. You +275 can now save a game and resume it at once (formerly you had to wait a +275 while first), but it now costs you a few points each time you save the +275 game. Saved games are now stored in much smaller files than before. +276 You don't have to say "go" every time; just specify a direction or, if +276 it's nearby, name the place to which you wish to move. +-1 +7 +1 3 +2 3 +3 8 9 +4 10 +5 11 +6 0 +7 14 15 +8 13 +9 94 -1 +10 96 +11 19 -1 +12 17 27 +13 101 -1 +14 103 +15 0 +16 106 +17 0 -1 +18 0 +19 3 +20 3 +21 0 +22 0 +23 109 -1 +24 25 -1 +25 23 67 +26 111 -1 +27 35 110 +28 0 +29 97 -1 +30 0 -1 +31 119 121 +32 117 122 +33 117 122 +34 0 0 +35 130 -1 +36 0 -1 +37 126 -1 +38 140 -1 +39 0 +40 96 -1 +41 143 -1 +42 6 -1 +43 0 -1 +44 0 -1 +45 113 169 +46 166 +47 11 -1 +48 18 -1 +49 106 -1 +50 18 +51 27 +52 28 +53 29 +54 30 +55 0 +56 92 +57 95 +58 97 +59 100 +60 101 +61 0 +62 119 121 +63 127 +64 130 -1 +65 144 +66 0 +67 0 +68 167 +69 177 +-1 +8 +1 24 +2 29 +3 0 +4 33 +5 0 +6 33 +7 195 +8 195 +9 42 +10 14 +11 43 +12 110 +13 29 +14 110 +15 73 +16 75 +17 29 +18 61 +19 59 +20 59 +21 174 +22 109 +23 67 +24 61 +25 147 +26 155 +27 195 +28 146 +29 110 +30 61 +31 61 +32 14 +33 195 +34 42 +35 61 +-1 +9 +0 1 2 3 4 5 6 7 8 9 10 +0 100 115 116 126 145 146 147 148 149 150 +0 151 152 153 154 155 156 157 158 159 160 +0 161 162 163 164 165 166 167 +2 1 3 4 7 38 95 113 24 168 169 +1 24 +3 46 47 48 54 56 58 82 85 86 +3 122 123 124 125 126 127 128 129 130 +4 6 145 146 147 148 149 150 151 152 +4 153 154 155 156 157 158 159 160 161 +4 162 163 164 165 166 42 43 44 45 +4 49 50 51 52 53 55 57 80 83 +4 84 87 107 112 131 132 133 134 135 +4 136 137 138 139 108 +11 8 +12 13 +13 19 +14 42 43 44 45 46 47 48 49 50 51 +14 52 53 54 55 56 80 81 82 86 87 +15 99 100 101 +16 108 +17 6 +18 145 146 147 148 149 150 151 152 153 154 +18 155 156 157 158 159 160 161 162 163 164 +18 165 166 +19 143 +20 8 15 64 109 126 +-1 +10 +45 You are obviously a rank amateur. Better luck next time. +120 Your score qualifies you as a novice class adventurer. +170 You have achieved the rating: "Experienced Adventurer". +250 You may now consider yourself a "Seasoned Adventurer". +320 You have reached "Junior Master" status. +375 Your score puts you in Master Adventurer Class C. +410 Your score puts you in Master Adventurer Class B. +426 Your score puts you in Master Adventurer Class A. +429 All of Adventuredom gives tribute to you, Adventurer Grandmaster! +9999 Adventuredom stands in awe -- you have now joined the ranks of the +9999 W O R L D C H A M P I O N A D V E N T U R E R S ! +9999 It may interest you to know that the Dungeon-Master himself has, to +9999 my knowledge, never achieved this threshhold in fewer than 330 turns. +-1 +11 +1 4 2 62 63 +2 5 2 18 19 +3 8 2 20 21 +4 75 4 176 177 +5 25 5 178 179 +6 20 3 180 181 +7 8 2 243 244 +8 25 2 247 248 +9 10 4 191 194 +10 1 4 272 273 +-1 +13 +8 3 -1 +11 2 -1 +13 -1 1 +14 1 -1 +15 2 -1 +16 -1 1 +24 6 -1 +31 4 -1 +33 3 -1 +36 -1 1 +38 -1 1 +41 1 -1 +47 -1 1 +48 -1 1 +49 -1 1 +1 229 +3 229 +4 229 +7 229 +15 230 +38 229 +64 230 +94 230 +95 231 +98 232 +109 230 +113 231 +115 233 +116 234 +123 235 +124 235 +125 236 +126 -237 +127 235 +168 -237 +169 249 +-1 +14 +200350 Tsk! A wizard wouldn't have to take 350 turns. This is going to cost +200350 you a couple of points. +300500 500 turns? That's another few points you've lost. +501000 Are you still at it? Five points off for exceeding 1000 turns! +1002500 Good grief, don't you *EVER* give up? Do you realize you've spent +1002500 over 2500 turns at this? That's another ten points off, a total of +1002500 twenty points lost for taking so long. +-1 +0 diff --git a/copyright b/copyright new file mode 100644 index 0000000..df9ea10 --- /dev/null +++ b/copyright @@ -0,0 +1,6 @@ +Don Wood's Adventure 2.5: (c) Copyright 1995 by Donald R. Woods. + +This software may be freely redistributed if this notice is retained. +(The author apologises for the style of the code; it is a result of +running the original Fortran IV source through a home-brew Fortran-to-C +converter.) diff --git a/datime.c b/datime.c new file mode 100644 index 0000000..0fa30de --- /dev/null +++ b/datime.c @@ -0,0 +1,50 @@ +#ifdef AMIGA +#define _TIME_ +#include "exec/types.h" +#include "intuition/intuition.h" + +#define INTUITIONREV 1 + +struct IntuitionBase *IntuitionBase = NULL; + +fDATIME(X,Y)int *X, *Y; { +static int GOTX = 0, GOTY; + if(GOTX == 0) { + IntuitionBase = (struct IntuitionBase *) + OpenLibrary("intuition.library", INTUITIONREV); + if (IntuitionBase == NULL) { + printf("Can't open library.\n"); + exit(FALSE); + } + CurrentTime(&GOTX, &GOTY); + CloseLibrary(IntuitionBase); + } + GOTY += 654321; + if(GOTY >= 1000000) {GOTX += 1; GOTY -= 1000000;} + *X = GOTX; + *Y = GOTY; +} +#endif + +#ifdef __MSDOS__ +#define _TIME_ +#include "time.h" + +fDATIME(X,Y)long *X, *Y; { + time(X); time(Y); + *Y /= 2; + /* it would be even better if the two numbers were totally + * unrelated, like if 'time' returned 64 bits of data */ +} +#endif + +#ifndef _TIME_ +#include "sys/time.h" + +fDATIME(X,Y)long *X, *Y; { + struct timeval now; + gettimeofday(&now, 0); + *X = now.tv_sec; + *Y = now.tv_usec; +} +#endif diff --git a/funcs.h b/funcs.h new file mode 100644 index 0000000..0daecee --- /dev/null +++ b/funcs.h @@ -0,0 +1,40 @@ +/* STATEMENT FUNCTIONS + * + * AT(OBJ) = TRUE IF ON EITHER SIDE OF TWO-PLACED OBJECT + * CNDBIT(L,N) = TRUE IF COND(L) HAS BIT N SET (BIT 0 IS UNITS BIT) + * DARK(DUMMY) = TRUE IF LOCATION "LOC" IS DARK + * FORCED(LOC) = TRUE IF LOC MOVES WITHOUT ASKING FOR INPUT (COND=2) + * FOREST(LOC) = TRUE IF LOC IS PART OF THE FOREST + * GSTONE(OBJ) = TRUE IF OBJ IS A GEMSTONE + * HERE(OBJ) = TRUE IF THE OBJ IS AT "LOC" (OR IS BEING CARRIED) + * LIQ(DUMMY) = OBJECT NUMBER OF LIQUID IN BOTTLE + * LIQLOC(LOC) = OBJECT NUMBER OF LIQUID (IF ANY) AT LOC + * PCT(N) = TRUE N% OF THE TIME (N INTEGER FROM 0 TO 100) + * TOTING(OBJ) = TRUE IF THE OBJ IS BEING CARRIED */ + +#define TOTING(OBJ) (PLACE[OBJ] == -1) +#define AT(OBJ) (PLACE[OBJ] == LOC || FIXED[OBJ] == LOC) +#define HERE(OBJ) (AT(OBJ) || TOTING(OBJ)) +#define LIQ2(PBOTL) ((1-(PBOTL))*WATER+((PBOTL)/2)*(WATER+OIL)) +#define LIQ(DUMMY) (LIQ2(PROP[BOTTLE]<0 ? -1-PROP[BOTTLE] : PROP[BOTTLE])) +#define LIQLOC(LOC) (LIQ2((MOD(COND[LOC]/2*2,8)-5)*MOD(COND[LOC]/4,2)+1)) +#define CNDBIT(L,N) (TSTBIT(COND[L],N)) +#define FORCED(LOC) (COND[LOC] == 2) +#define DARK(DUMMY) ((!CNDBIT(LOC,0)) && (PROP[LAMP] == 0 || !HERE(LAMP))) +#define PCT(N) (RAN(100) < (N)) +#define GSTONE(OBJ) ((OBJ) == EMRALD || (OBJ) == RUBY || (OBJ) == AMBER || (OBJ) == SAPPH) +#define FOREST(LOC) ((LOC) >= 145 && (LOC) <= 166) +#define VOCWRD(LETTRS,SECT) (VOCAB(MAKEWD(LETTRS),SECT)) + +/* THE FOLLOWING TWO FUNCTIONS WERE ADDED TO FIX A BUG (CLOCK1 DECREMENTED + * WHILE IN FOREST). THEY SHOULD PROBABLY BE REPLACED BY USING ANOTHER + * "COND" BIT. FOR NOW, HOWEVER, A QUICK FIX... OUTSID(LOC) IS TRUE IF + * LOC IS OUTSIDE, INDEEP(LOC) IS TRUE IF LOC IS "DEEP" IN THE CAVE (HALL + * OF MISTS OR DEEPER). NOTE SPECIAL KLUDGES FOR "FOOF" LOCS. */ + +#define OUTSID(LOC) ((LOC) <= 8 || FOREST(LOC) || (LOC) == PLAC[SAPPH] || (LOC) == 180 || (LOC) == 182) +#define INDEEP(LOC) ((LOC) >= 15 && !OUTSID(LOC) && (LOC) != 179) + + + + diff --git a/init.c b/init.c new file mode 100644 index 0000000..6b2edea --- /dev/null +++ b/init.c @@ -0,0 +1,708 @@ +#include "misc.h" +#include "main.h" +#include "share.h" +#include "funcs.h" +#include + +#define TRUE (0==0) +#define FALSE (0!=0) + +/* + * INITIALISATION + */ + +/* CURRENT LIMITS: + * 12500 WORDS OF MESSAGE TEXT (LINES, LINSIZ). + * 885 TRAVEL OPTIONS (TRAVEL, TRVSIZ). + * 330 VOCABULARY WORDS (KTAB, ATAB, TABSIZ). + * 185 LOCATIONS (LTEXT, STEXT, KEY, COND, ABB, ATLOC, LOCSND, LOCSIZ). + * 100 OBJECTS (PLAC, PLACE, FIXD, FIXED, LINK (TWICE), PTEXT, PROP, + * OBJSND, OBJTXT). + * 35 "ACTION" VERBS (ACTSPK, VRBSIZ). + * 277 RANDOM MESSAGES (RTEXT, RTXSIZ). + * 12 DIFFERENT PLAYER CLASSIFICATIONS (CTEXT, CVAL, CLSMAX). + * 20 HINTS (HINTLC, HINTED, HINTS, HNTSIZ). + * 5 "# OF TURNS" THRESHHOLDS (TTEXT, TRNVAL, TRNSIZ). + * THERE ARE ALSO LIMITS WHICH CANNOT BE EXCEEDED DUE TO THE STRUCTURE OF + * THE DATABASE. (E.G., THE VOCABULARY USES N/1000 TO DETERMINE WORD TYPE, + * SO THERE CAN'T BE MORE THAN 1000 WORDS.) THESE UPPER LIMITS ARE: + * 1000 NON-SYNONYMOUS VOCABULARY WORDS + * 300 LOCATIONS + * 100 OBJECTS */ + + +/* DESCRIPTION OF THE DATABASE FORMAT + * + * + * THE DATA FILE CONTAINS SEVERAL SECTIONS. EACH BEGINS WITH A LINE CONTAINING + * A NUMBER IDENTIFYING THE SECTION, AND ENDS WITH A LINE CONTAINING "-1". + * + * SECTION 1: LONG FORM DESCRIPTIONS. EACH LINE CONTAINS A LOCATION NUMBER, + * A TAB, AND A LINE OF TEXT. THE SET OF (NECESSARILY ADJACENT) LINES + * WHOSE NUMBERS ARE X FORM THE LONG DESCRIPTION OF LOCATION X. + * SECTION 2: SHORT FORM DESCRIPTIONS. SAME FORMAT AS LONG FORM. NOT ALL + * PLACES HAVE SHORT DESCRIPTIONS. + * SECTION 3: TRAVEL TABLE. EACH LINE CONTAINS A LOCATION NUMBER (X), A SECOND + * LOCATION NUMBER (Y), AND A LIST OF MOTION NUMBERS (SEE SECTION 4). + * EACH MOTION REPRESENTS A VERB WHICH WILL GO TO Y IF CURRENTLY AT X. + * Y, IN TURN, IS INTERPRETED AS FOLLOWS. LET M=Y/1000, N=Y MOD 1000. + * IF N<=300 IT IS THE LOCATION TO GO TO. + * IF 300500 MESSAGE N-500 FROM SECTION 6 IS PRINTED, + * AND HE STAYS WHEREVER HE IS. + * MEANWHILE, M SPECIFIES THE CONDITIONS ON THE MOTION. + * IF M=0 IT'S UNCONDITIONAL. + * IF 0$<". + * SECTION 6: ARBITRARY MESSAGES. SAME FORMAT AS SECTIONS 1, 2, AND 5, EXCEPT + * THE NUMBERS BEAR NO RELATION TO ANYTHING (EXCEPT FOR SPECIAL VERBS + * IN SECTION 4). + * SECTION 7: OBJECT LOCATIONS. EACH LINE CONTAINS AN OBJECT NUMBER AND ITS + * INITIAL LOCATION (ZERO (OR OMITTED) IF NONE). IF THE OBJECT IS + * IMMOVABLE, THE LOCATION IS FOLLOWED BY A "-1". IF IT HAS TWO LOCATIONS + * (E.G. THE GRATE) THE FIRST LOCATION IS FOLLOWED WITH THE SECOND, AND + * THE OBJECT IS ASSUMED TO BE IMMOVABLE. + * SECTION 8: ACTION DEFAULTS. EACH LINE CONTAINS AN "ACTION-VERB" NUMBER AND + * THE INDEX (IN SECTION 6) OF THE DEFAULT MESSAGE FOR THE VERB. + * SECTION 9: LOCATION ATTRIBUTES. EACH LINE CONTAINS A NUMBER (N) AND UP TO + * 20 LOCATION NUMBERS. BIT N (WHERE 0 IS THE UNITS BIT) IS SET IN + * COND(LOC) FOR EACH LOC GIVEN. THE COND BITS CURRENTLY ASSIGNED ARE: + * 0 LIGHT + * 1 IF BIT 2 IS ON: ON FOR OIL, OFF FOR WATER + * 2 LIQUID ASSET, SEE BIT 1 + * 3 PIRATE DOESN'T GO HERE UNLESS FOLLOWING PLAYER + * 4 CANNOT USE "BACK" TO MOVE AWAY + * BITS PAST 10 INDICATE AREAS OF INTEREST TO "HINT" ROUTINES: + * 11 TRYING TO GET INTO CAVE + * 12 TRYING TO CATCH BIRD + * 13 TRYING TO DEAL WITH SNAKE + * 14 LOST IN MAZE + * 15 PONDERING DARK ROOM + * 16 AT WITT'S END + * 17 CLIFF WITH URN + * 18 LOST IN FOREST + * 19 TRYING TO DEAL WITH OGRE + * 20 FOUND ALL TREASURES EXCEPT JADE + * COND(LOC) IS SET TO 2, OVERRIDING ALL OTHER BITS, IF LOC HAS FORCED + * MOTION. + * SECTION 10: CLASS MESSAGES. EACH LINE CONTAINS A NUMBER (N), A TAB, AND A + * MESSAGE DESCRIBING A CLASSIFICATION OF PLAYER. THE SCORING SECTION + * SELECTS THE APPROPRIATE MESSAGE, WHERE EACH MESSAGE IS CONSIDERED TO + * APPLY TO PLAYERS WHOSE SCORES ARE HIGHER THAN THE PREVIOUS N BUT NOT + * HIGHER THAN THIS N. NOTE THAT THESE SCORES PROBABLY CHANGE WITH EVERY + * MODIFICATION (AND PARTICULARLY EXPANSION) OF THE PROGRAM. + * SECTION 11: HINTS. EACH LINE CONTAINS A HINT NUMBER (ADD 10 TO GET COND + * BIT; SEE SECTION 9), THE NUMBER OF TURNS HE MUST BE AT THE RIGHT LOC(S) + * BEFORE TRIGGERING THE HINT, THE POINTS DEDUCTED FOR TAKING THE HINT, + * THE MESSAGE NUMBER (SECTION 6) OF THE QUESTION, AND THE MESSAGE NUMBER + * OF THE HINT. THESE VALUES ARE STASHED IN THE "HINTS" ARRAY. HNTMAX IS + * SET TO THE MAX HINT NUMBER (<= HNTSIZ). + * SECTION 12: UNUSED IN THIS VERSION. + * SECTION 13: SOUNDS AND TEXT. EACH LINE CONTAINS EITHER 2 OR 3 NUMBERS. IF + * 2 (CALL THEM N AND S), N IS A LOCATION AND MESSAGE ABS(S) FROM SECTION + * 6 IS THE SOUND HEARD THERE. IF S<0, THE SOUND THERE DROWNS OUT ALL + * OTHER NOISES. IF 3 NUMBERS (CALL THEM N, S, AND T), N IS AN OBJECT + * NUMBER AND S+PROP(N) IS THE PROPERTY MESSAGE (FROM SECTION 5) IF HE + * LISTENS TO THE OBJECT, AND T+PROP(N) IS THE TEXT IF HE READS IT. IF + * S OR T IS -1, THE OBJECT HAS NO SOUND OR TEXT, RESPECTIVELY. NEITHER + * S NOR T IS ALLOWED TO BE 0. + * SECTION 14: TURN THRESHHOLDS. EACH LINE CONTAINS A NUMBER (N), A TAB, AND + * A MESSAGE BERATING THE PLAYER FOR TAKING SO MANY TURNS. THE MESSAGES + * MUST BE IN THE PROPER (ASCENDING) ORDER. THE MESSAGE GETS PRINTED IF + * THE PLAYER EXCEEDS N MOD 100000 TURNS, AT WHICH TIME N/100000 POINTS + * GET DEDUCTED FROM HIS SCORE. + * SECTION 0: END OF DATABASE. */ + +/* THE VARIOUS MESSAGES (SECTIONS 1, 2, 5, 6, ETC.) MAY INCLUDE CERTAIN + * SPECIAL CHARACTER SEQUENCES TO DENOTE THAT THE PROGRAM MUST PROVIDE + * PARAMETERS TO INSERT INTO A MESSAGE WHEN THE MESSAGE IS PRINTED. THESE + * SEQUENCES ARE: + * %S = THE LETTER 'S' OR NOTHING (IF A GIVEN VALUE IS EXACTLY 1) + * %W = A WORD (UP TO 10 CHARACTERS) + * %L = A WORD MAPPED TO LOWER-CASE LETTERS + * %U = A WORD MAPPED TO UPPER-CASE LETTERS + * %C = A WORD MAPPED TO LOWER-CASE, FIRST LETTER CAPITALISED + * %T = SEVERAL WORDS OF TEXT, ENDING WITH A WORD OF -1 + * %1 = A 1-DIGIT NUMBER + * %2 = A 2-DIGIT NUMBER + * ... + * %9 = A 9-DIGIT NUMBER + * %B = VARIABLE NUMBER OF BLANKS + * %! = THE ENTIRE MESSAGE SHOULD BE SUPPRESSED */ + +initialise() { + printf("Initialising...\n"); + if(!quick_init()){raw_init(); report(); quick_save();} + finish_init(); +} + +static raw_init() { + printf("Couldn't find adventure.data, using adventure.text...\n"); + +/* CLEAR OUT THE VARIOUS TEXT-POINTER ARRAYS. ALL TEXT IS STORED IN ARRAY + * LINES; EACH LINE IS PRECEDED BY A WORD POINTING TO THE NEXT POINTER (I.E. + * THE WORD FOLLOWING THE END OF THE LINE). THE POINTER IS NEGATIVE IF THIS IS + * FIRST LINE OF A MESSAGE. THE TEXT-POINTER ARRAYS CONTAIN INDICES OF + * POINTER-WORDS IN LINES. STEXT(N) IS SHORT DESCRIPTION OF LOCATION N. + * LTEXT(N) IS LONG DESCRIPTION. PTEXT(N) POINTS TO MESSAGE FOR PROP(N)=0. + * SUCCESSIVE PROP MESSAGES ARE FOUND BY CHASING POINTERS. RTEXT CONTAINS + * SECTION 6'S STUFF. CTEXT(N) POINTS TO A PLAYER-CLASS MESSAGE. TTEXT IS FOR + * SECTION 14. WE ALSO CLEAR COND (SEE DESCRIPTION OF SECTION 9 FOR DETAILS). */ + + /* 1001 */ for (I=1; I<=300; I++) { + if(I <= 100)PTEXT[I]=0; + if(I <= RTXSIZ)RTEXT[I]=0; + if(I <= CLSMAX)CTEXT[I]=0; + if(I <= 100)OBJSND[I]=0; + if(I <= 100)OBJTXT[I]=0; + if(I > LOCSIZ) goto L1001; + STEXT[I]=0; + LTEXT[I]=0; + COND[I]=0; + KEY[I]=0; + LOCSND[I]=0; +L1001: /*etc*/ ; + } /* end loop */ + + LINUSE=1; + TRVS=1; + CLSSES=0; + TRNVLS=0; + +/* START NEW DATA SECTION. SECT IS THE SECTION NUMBER. */ + +L1002: SECT=GETNUM(1); + OLDLOC= -1; + switch (SECT) { case 0: return(0); case 1: goto L1004; case 2: goto + L1004; case 3: goto L1030; case 4: goto L1040; case 5: goto L1004; + case 6: goto L1004; case 7: goto L1050; case 8: goto L1060; case + 9: goto L1070; case 10: goto L1004; case 11: goto L1080; case 12: + break; case 13: goto L1090; case 14: goto L1004; } +/* (0) (1) (2) (3) (4) (5) (6) (7) (8) (9) + * (10) (11) (12) (13) (14) */ + BUG(9); + +/* SECTIONS 1, 2, 5, 6, 10, 14. READ MESSAGES AND SET UP POINTERS. */ + +L1004: KK=LINUSE; +L1005: LINUSE=KK; + LOC=GETNUM(1); + if(LNLENG >= LNPOSN+70)BUG(0); + if(LOC == -1) goto L1002; + if(LNLENG < LNPOSN)BUG(1); +L1006: KK=KK+1; + if(KK >= LINSIZ)BUG(2); + LINES[KK]=GETTXT(FALSE,FALSE,FALSE,KK); + if(LINES[KK] != -1) goto L1006; + LINES[LINUSE]=KK; + if(LOC == OLDLOC) goto L1005; + OLDLOC=LOC; + LINES[LINUSE]= -KK; + if(SECT == 14) goto L1014; + if(SECT == 10) goto L1012; + if(SECT == 6) goto L1011; + if(SECT == 5) goto L1010; + if(LOC > LOCSIZ)BUG(10); + if(SECT == 1) goto L1008; + + STEXT[LOC]=LINUSE; + goto L1005; + +L1008: LTEXT[LOC]=LINUSE; + goto L1005; + +L1010: if(LOC > 0 && LOC <= 100)PTEXT[LOC]=LINUSE; + goto L1005; + +L1011: if(LOC > RTXSIZ)BUG(6); + RTEXT[LOC]=LINUSE; + goto L1005; + +L1012: CLSSES=CLSSES+1; + if(CLSSES > CLSMAX)BUG(11); + CTEXT[CLSSES]=LINUSE; + CVAL[CLSSES]=LOC; + goto L1005; + +L1014: TRNVLS=TRNVLS+1; + if(TRNVLS > TRNSIZ)BUG(11); + TTEXT[TRNVLS]=LINUSE; + TRNVAL[TRNVLS]=LOC; + goto L1005; + +/* THE STUFF FOR SECTION 3 IS ENCODED HERE. EACH "FROM-LOCATION" GETS A + * CONTIGUOUS SECTION OF THE "TRAVEL" ARRAY. EACH ENTRY IN TRAVEL IS + * NEWLOC*1000 + KEYWORD (FROM SECTION 4, MOTION VERBS), AND IS NEGATED IF + * THIS IS THE LAST ENTRY FOR THIS LOCATION. KEY(N) IS THE INDEX IN TRAVEL + * OF THE FIRST OPTION AT LOCATION N. */ + +L1030: LOC=GETNUM(1); + if(LOC == -1) goto L1002; + NEWLOC=GETNUM(0); + if(KEY[LOC] != 0) goto L1033; + KEY[LOC]=TRVS; + goto L1035; +L1033: TRVS--; TRAVEL[TRVS]= -TRAVEL[TRVS]; TRVS++; +L1035: L=GETNUM(0); + if(L == 0) goto L1039; + TRAVEL[TRVS]=NEWLOC*1000+L; + TRVS=TRVS+1; + if(TRVS == TRVSIZ)BUG(3); + goto L1035; +L1039: TRVS--; TRAVEL[TRVS]= -TRAVEL[TRVS]; TRVS++; + goto L1030; + +/* HERE WE READ IN THE VOCABULARY. KTAB(N) IS THE WORD NUMBER, ATAB(N) IS + * THE CORRESPONDING WORD. THE -1 AT THE END OF SECTION 4 IS LEFT IN KTAB + * AS AN END-MARKER. THE WORDS ARE GIVEN A MINIMAL HASH TO MAKE DECIPHERING + * THE CORE-IMAGE HARDER. (WE DON'T USE GETTXT'S HASH SINCE THAT WOULD FORCE + * US TO HASH EACH INPUT LINE TO MAKE COMPARISONS WORK, AND THAT IN TURN + * WOULD MAKE IT HARDER TO DETECT PARTICULAR INPUT WORDS.) */ + +L1040: J=10000; + /* 1042 */ for (TABNDX=1; TABNDX<=TABSIZ; TABNDX++) { +L1043: KTAB[TABNDX]=GETNUM(1); + if(KTAB[TABNDX] == -1) goto L1002; + J=J+7; +L1042: ATAB[TABNDX]=GETTXT(TRUE,TRUE,TRUE,0)+J*J; + } /* end loop */ + BUG(4); + +/* READ IN THE INITIAL LOCATIONS FOR EACH OBJECT. ALSO THE IMMOVABILITY INFO. + * PLAC CONTAINS INITIAL LOCATIONS OF OBJECTS. FIXD IS -1 FOR IMMOVABLE + * OBJECTS (INCLUDING THE SNAKE), OR = SECOND LOC FOR TWO-PLACED OBJECTS. */ + +L1050: OBJ=GETNUM(1); + if(OBJ == -1) goto L1002; + PLAC[OBJ]=GETNUM(0); + FIXD[OBJ]=GETNUM(0); + goto L1050; + +/* READ DEFAULT MESSAGE NUMBERS FOR ACTION VERBS, STORE IN ACTSPK. */ + +L1060: VERB=GETNUM(1); + if(VERB == -1) goto L1002; + ACTSPK[VERB]=GETNUM(0); + goto L1060; + +/* READ INFO ABOUT AVAILABLE LIQUIDS AND OTHER CONDITIONS, STORE IN COND. */ + +L1070: K=GETNUM(1); + if(K == -1) goto L1002; +L1071: LOC=GETNUM(0); + if(LOC == 0) goto L1070; + if(CNDBIT(LOC,K)) BUG(8); + COND[LOC]=COND[LOC]+SETBIT(K); + goto L1071; + +/* READ DATA FOR HINTS. */ + +L1080: HNTMAX=0; +L1081: K=GETNUM(1); + if(K == -1) goto L1002; + if(K <= 0 || K > HNTSIZ)BUG(7); + /* 1083 */ for (I=1; I<=4; I++) { +L1083: HINTS[K][I] =GETNUM(0); + } /* end loop */ + HNTMAX=(HNTMAX>K ? HNTMAX : K); + goto L1081; + +/* READ THE SOUND/TEXT INFO, STORE IN OBJSND, OBJTXT, LOCSND. */ + +L1090: K=GETNUM(1); + if(K == -1) goto L1002; + KK=GETNUM(0); + I=GETNUM(0); + if(I == 0) goto L1092; + OBJSND[K]=(KK>0 ? KK : 0); + OBJTXT[K]=(I>0 ? I : 0); + goto L1090; + +L1092: LOCSND[K]=KK; + goto L1090; +} + +/* FINISH CONSTRUCTING INTERNAL DATA FORMAT */ + +/* HAVING READ IN THE DATABASE, CERTAIN THINGS ARE NOW CONSTRUCTED. PROPS ARE + * SET TO ZERO. WE FINISH SETTING UP COND BY CHECKING FOR FORCED-MOTION TRAVEL + * ENTRIES. THE PLAC AND FIXD ARRAYS ARE USED TO SET UP ATLOC(N) AS THE FIRST + * OBJECT AT LOCATION N, AND LINK(OBJ) AS THE NEXT OBJECT AT THE SAME LOCATION + * AS OBJ. (OBJ>100 INDICATES THAT FIXED(OBJ-100)=LOC; LINK(OBJ) IS STILL THE + * CORRECT LINK TO USE.) ABB IS ZEROED; IT CONTROLS WHETHER THE ABBREVIATED + * DESCRIPTION IS PRINTED. COUNTS MOD 5 UNLESS "LOOK" IS USED. */ + +static finish_init() { + /* 1101 */ for (I=1; I<=100; I++) { + PLACE[I]=0; + PROP[I]=0; + LINK[I]=0; +L1101: {long x = I+100; LINK[x]=0;} + } /* end loop */ + + /* 1102 */ for (I=1; I<=LOCSIZ; I++) { + ABB[I]=0; + if(LTEXT[I] == 0 || KEY[I] == 0) goto L1102; + K=KEY[I]; + if(MOD(IABS(TRAVEL[K]),1000) == 1)COND[I]=2; +L1102: ATLOC[I]=0; + } /* end loop */ + +/* SET UP THE ATLOC AND LINK ARRAYS AS DESCRIBED ABOVE. WE'LL USE THE DROP + * SUBROUTINE, WHICH PREFACES NEW OBJECTS ON THE LISTS. SINCE WE WANT THINGS + * IN THE OTHER ORDER, WE'LL RUN THE LOOP BACKWARDS. IF THE OBJECT IS IN TWO + * LOCS, WE DROP IT TWICE. THIS ALSO SETS UP "PLACE" AND "FIXED" AS COPIES OF + * "PLAC" AND "FIXD". ALSO, SINCE TWO-PLACED OBJECTS ARE TYPICALLY BEST + * DESCRIBED LAST, WE'LL DROP THEM FIRST. */ + + /* 1106 */ for (I=1; I<=100; I++) { + K=101-I; + if(FIXD[K] <= 0) goto L1106; + DROP(K+100,FIXD[K]); + DROP(K,PLAC[K]); +L1106: /*etc*/ ; + } /* end loop */ + + /* 1107 */ for (I=1; I<=100; I++) { + K=101-I; + FIXED[K]=FIXD[K]; +L1107: if(PLAC[K] != 0 && FIXD[K] <= 0)DROP(K,PLAC[K]); + } /* end loop */ + +/* TREASURES, AS NOTED EARLIER, ARE OBJECTS 50 THROUGH MAXTRS (CURRENTLY 79). + * THEIR PROPS ARE INITIALLY -1, AND ARE SET TO 0 THE FIRST TIME THEY ARE + * DESCRIBED. TALLY KEEPS TRACK OF HOW MANY ARE NOT YET FOUND, SO WE KNOW + * WHEN TO CLOSE THE CAVE. */ + + MAXTRS=79; + TALLY=0; + /* 1200 */ for (I=50; I<=MAXTRS; I++) { + if(PTEXT[I] != 0)PROP[I]= -1; +L1200: TALLY=TALLY-PROP[I]; + } /* end loop */ + +/* CLEAR THE HINT STUFF. HINTLC(I) IS HOW LONG HE'S BEEN AT LOC WITH COND BIT + * I. HINTED(I) IS TRUE IFF HINT I HAS BEEN USED. */ + + /* 1300 */ for (I=1; I<=HNTMAX; I++) { + HINTED[I]=FALSE; +L1300: HINTLC[I]=0; + } /* end loop */ + +/* DEFINE SOME HANDY MNEMONICS. THESE CORRESPOND TO OBJECT NUMBERS. */ + + AXE=VOCWRD(12405,1); + BATTER=VOCWRD(201202005,1); + BEAR=VOCWRD(2050118,1); + BIRD=VOCWRD(2091804,1); + BLOOD=VOCWRD(212151504,1); + BOTTLE=VOCWRD(215202012,1); + CAGE=VOCWRD(3010705,1); + CAVITY=VOCWRD(301220920,1); + CHASM=VOCWRD(308011913,1); + CLAM=VOCWRD(3120113,1); + DOOR=VOCWRD(4151518,1); + DRAGON=VOCWRD(418010715,1); + DWARF=VOCWRD(423011806,1); + FISSUR=VOCWRD(609191921,1); + FOOD=VOCWRD(6151504,1); + GRATE=VOCWRD(718012005,1); + KEYS=VOCWRD(11052519,1); + KNIFE=VOCWRD(1114090605,1); + LAMP=VOCWRD(12011316,1); + MAGZIN=VOCWRD(1301070126,1); + MESSAG=VOCWRD(1305191901,1); + MIRROR=VOCWRD(1309181815,1); + OGRE=VOCWRD(15071805,1); + OIL=VOCWRD(150912,1); + OYSTER=VOCWRD(1525192005,1); + PILLOW=VOCWRD(1609121215,1); + PLANT=VOCWRD(1612011420,1); + PLANT2=PLANT+1; + RESER=VOCWRD(1805190518,1); + ROD=VOCWRD(181504,1); + ROD2=ROD+1; + SIGN=VOCWRD(19090714,1); + SNAKE=VOCWRD(1914011105,1); + STEPS=VOCWRD(1920051619,1); + TROLL=VOCWRD(2018151212,1); + TROLL2=TROLL+1; + URN=VOCWRD(211814,1); + VEND=VOCWRD(1755140409,1); + VOLCAN=VOCWRD(1765120301,1); + WATER=VOCWRD(1851200518,1); + +/* OBJECTS FROM 50 THROUGH WHATEVER ARE TREASURES. HERE ARE A FEW. */ + + AMBER=VOCWRD(113020518,1); + CHAIN=VOCWRD(308010914,1); + CHEST=VOCWRD(308051920,1); + COINS=VOCWRD(315091419,1); + EGGS=VOCWRD(5070719,1); + EMRALD=VOCWRD(513051801,1); + JADE=VOCWRD(10010405,1); + NUGGET=VOCWRD(7151204,1); + PEARL=VOCWRD(1605011812,1); + PYRAM=VOCWRD(1625180113,1); + RUBY=VOCWRD(18210225,1); + RUG=VOCWRD(182107,1); + SAPPH=VOCWRD(1901161608,1); + TRIDNT=VOCWRD(2018090405,1); + VASE=VOCWRD(22011905,1); + +/* THESE ARE MOTION-VERB NUMBERS. */ + + BACK=VOCWRD(2010311,0); + CAVE=VOCWRD(3012205,0); + DPRSSN=VOCWRD(405161805,0); + ENTER=VOCWRD(514200518,0); + ENTRNC=VOCWRD(514201801,0); + LOOK=VOCWRD(12151511,0); + NUL=VOCWRD(14211212,0); + STREAM=VOCWRD(1920180501,0); + +/* AND SOME ACTION VERBS. */ + + FIND=VOCWRD(6091404,2); + INVENT=VOCWRD(914220514,2); + LOCK=VOCWRD(12150311,2); + SAY=VOCWRD(190125,2); + THROW=VOCWRD(2008181523,2); + +/* INITIALISE THE DWARVES. DLOC IS LOC OF DWARVES, HARD-WIRED IN. ODLOC IS + * PRIOR LOC OF EACH DWARF, INITIALLY GARBAGE. DALTLC IS ALTERNATE INITIAL LOC + * FOR DWARF, IN CASE ONE OF THEM STARTS OUT ON TOP OF THE ADVENTURER. (NO 2 + * OF THE 5 INITIAL LOCS ARE ADJACENT.) DSEEN IS TRUE IF DWARF HAS SEEN HIM. + * DFLAG CONTROLS THE LEVEL OF ACTIVATION OF ALL THIS: + * 0 NO DWARF STUFF YET (WAIT UNTIL REACHES HALL OF MISTS) + * 1 REACHED HALL OF MISTS, BUT HASN'T MET FIRST DWARF + * 2 MET FIRST DWARF, OTHERS START MOVING, NO KNIVES THROWN YET + * 3 A KNIFE HAS BEEN THROWN (FIRST SET ALWAYS MISSES) + * 3+ DWARVES ARE MAD (INCREASES THEIR ACCURACY) + * SIXTH DWARF IS SPECIAL (THE PIRATE). HE ALWAYS STARTS AT HIS CHEST'S + * EVENTUAL LOCATION INSIDE THE MAZE. THIS LOC IS SAVED IN CHLOC FOR REF. + * THE DEAD END IN THE OTHER MAZE HAS ITS LOC STORED IN CHLOC2. */ + + CHLOC=114; + CHLOC2=140; + /* 1700 */ for (I=1; I<=6; I++) { +L1700: DSEEN[I]=FALSE; + } /* end loop */ + DFLAG=0; + DLOC[1]=19; + DLOC[2]=27; + DLOC[3]=33; + DLOC[4]=44; + DLOC[5]=64; + DLOC[6]=CHLOC; + DALTLC=18; + +/* OTHER RANDOM FLAGS AND COUNTERS, AS FOLLOWS: + * ABBNUM HOW OFTEN WE SHOULD PRINT NON-ABBREVIATED DESCRIPTIONS + * BONUS USED TO DETERMINE AMOUNT OF BONUS IF HE REACHES CLOSING + * CLOCK1 NUMBER OF TURNS FROM FINDING LAST TREASURE TILL CLOSING + * CLOCK2 NUMBER OF TURNS FROM FIRST WARNING TILL BLINDING FLASH + * CONDS MIN VALUE FOR COND(LOC) IF LOC HAS ANY HINTS + * DETAIL HOW OFTEN WE'VE SAID "NOT ALLOWED TO GIVE MORE DETAIL" + * DKILL NUMBER OF DWARVES KILLED (UNUSED IN SCORING, NEEDED FOR MSG) + * FOOBAR CURRENT PROGRESS IN SAYING "FEE FIE FOE FOO". + * HOLDNG NUMBER OF OBJECTS BEING CARRIED + * IGO HOW MANY TIMES HE'S SAID "GO XXX" INSTEAD OF "XXX" + * IWEST HOW MANY TIMES HE'S SAID "WEST" INSTEAD OF "W" + * KNFLOC 0 IF NO KNIFE HERE, LOC IF KNIFE HERE, -1 AFTER CAVEAT + * LIMIT LIFETIME OF LAMP (NOT SET HERE) + * MAXDIE NUMBER OF REINCARNATION MESSAGES AVAILABLE (UP TO 5) + * NUMDIE NUMBER OF TIMES KILLED SO FAR + * THRESH NEXT #TURNS THRESHHOLD (-1 IF NONE) + * TRNDEX INDEX IN TRNVAL OF NEXT THRESHHOLD (SECTION 14 OF DATABASE) + * TRNLUZ # POINTS LOST SO FAR DUE TO NUMBER OF TURNS USED + * TURNS TALLIES HOW MANY COMMANDS HE'S GIVEN (IGNORES YES/NO) + * LOGICALS WERE EXPLAINED EARLIER */ + + TURNS=0; + TRNDEX=1; + THRESH= -1; + if(TRNVLS > 0)THRESH=MOD(TRNVAL[1],100000)+1; + TRNLUZ=0; + LMWARN=FALSE; + IGO=0; + IWEST=0; + KNFLOC=0; + DETAIL=0; + ABBNUM=5; + /* 1800 */ for (I=0; I<=4; I++) { +L1800: {long x = 2*I+81; if(RTEXT[x] != 0)MAXDIE=I+1;} + } /* end loop */ + NUMDIE=0; + HOLDNG=0; + DKILL=0; + FOOBAR=0; + BONUS=0; + CLOCK1=30; + CLOCK2=50; + CONDS=SETBIT(11); + SAVED=0; + CLOSNG=FALSE; + PANIC=FALSE; + CLOSED=FALSE; + CLSHNT=FALSE; + NOVICE=FALSE; + SETUP=1; + + /* if we can ever think of how, we should save it at this point */ + + return(0); /* then we won't actually return from initialisation */ +} + +/* REPORT ON AMOUNT OF ARRAYS ACTUALLY USED, TO PERMIT REDUCTIONS. */ + +static report() { + /* 1998 */ for (K=1; K<=LOCSIZ; K++) { + KK=LOCSIZ+1-K; + if(LTEXT[KK] != 0) goto L1997; +L1998: /*etc*/ ; + } /* end loop */ + + OBJ=0; +L1997: /* 1996 */ for (K=1; K<=100; K++) { +L1996: if(PTEXT[K] != 0)OBJ=OBJ+1; + } /* end loop */ + + /* 1995 */ for (K=1; K<=TABNDX; K++) { +L1995: if(KTAB[K]/1000 == 2)VERB=KTAB[K]-2000; + } /* end loop */ + + /* 1994 */ for (K=1; K<=RTXSIZ; K++) { + J=RTXSIZ+1-K; + if(RTEXT[J] != 0) goto L1993; +L1994: /*etc*/ ; + } /* end loop */ + +L1993: SETPRM(1,LINUSE,LINSIZ); + SETPRM(3,TRVS,TRVSIZ); + SETPRM(5,TABNDX,TABSIZ); + SETPRM(7,KK,LOCSIZ); + SETPRM(9,OBJ,100); + SETPRM(11,VERB,VRBSIZ); + SETPRM(13,J,RTXSIZ); + SETPRM(15,CLSSES,CLSMAX); + SETPRM(17,HNTMAX,HNTSIZ); + SETPRM(19,TRNVLS,TRNSIZ); + RSPEAK(267); + TYPE0(); +} + +static long init_reading, init_cksum; +static FILE *f; + +static void quick_item(long*); +static void quick_array(long*, long); + +static quick_init() { +#ifdef AMIGA + f = fopen("ram:adventure.data", READ_MODE); +#else + extern char *getenv(); + char *adv = getenv("ADVENTURE"); + f = NULL; + if(adv)f = fopen(adv,READ_MODE); +#endif + if(f == NULL)f = fopen("adventure.data",READ_MODE); + if(f == NULL)return(FALSE); + init_reading = TRUE; + init_cksum = 1; + quick_io(); + if(fread(&K,4,1,f) == 1) init_cksum -= K; else init_cksum = 1; + fclose(f); + if(init_cksum != 0)printf("Checksum error!\n"); + return(init_cksum == 0); +} + +static quick_save() { + printf("Writing adventure.data...\n"); + f = fopen("adventure.data",WRITE_MODE); + if(f == NULL){printf("Can't open file!\n"); return(0);} + init_reading = FALSE; + init_cksum = 1; + quick_io(); + fwrite(&init_cksum,4,1,f); + fclose(f); + return(0); +} + +static quick_io() { + quick_item(&LINUSE); + quick_item(&TRVS); + quick_item(&CLSSES); + quick_item(&TRNVLS); + quick_item(&TABNDX); + quick_item(&HNTMAX); + quick_array(PTEXT,100); + quick_array(RTEXT,RTXSIZ); + quick_array(CTEXT,CLSMAX); + quick_array(OBJSND,100); + quick_array(OBJTXT,100); + quick_array(STEXT,LOCSIZ); + quick_array(LTEXT,LOCSIZ); + quick_array(COND,LOCSIZ); + quick_array(KEY,LOCSIZ); + quick_array(LOCSND,LOCSIZ); + quick_array(LINES,LINSIZ); + quick_array(CVAL,CLSMAX); + quick_array(TTEXT,TRNSIZ); + quick_array(TRNVAL,TRNSIZ); + quick_array(TRAVEL,TRVSIZ); + quick_array(KTAB,TABSIZ); + quick_array(ATAB,TABSIZ); + quick_array(PLAC,100); + quick_array(FIXD,100); + quick_array(ACTSPK,VRBSIZ); + quick_array((long *)HINTS,(HNTMAX+1)*5-1); + return(0); +} + +static void quick_item(W)long *W; { + if(init_reading && fread(W,4,1,f) != 1)return; + init_cksum = MOD(init_cksum*13+(*W),60000000); + if(!init_reading)fwrite(W,4,1,f); +} + +static void quick_array(A,N)long *A, N; { long I; + if(init_reading && fread(A,4,N+1,f) != N+1)printf("Read error!\n"); + for(I=1;I<=N;I++)init_cksum = MOD(init_cksum*13+A[I],60000000); + if(!init_reading && fwrite(A,4,N+1,f)!=N+1)printf("Write error!\n"); +} diff --git a/main.c b/main.c new file mode 100644 index 0000000..6977bc5 --- /dev/null +++ b/main.c @@ -0,0 +1,859 @@ +#include "misc.h" +#ifdef __MSDOS__ +#include "alloc.h" +#endif + +#define TRUE (0==0) +#define FALSE (0!=0) +long ABB[186], ATAB[331], ATLOC[186], BLKLIN = TRUE, DFLAG, + DLOC[7], FIXED[101], HOLDNG, + KTAB[331], *LINES, LINK[201], LNLENG, LNPOSN, + PARMS[26], PLACE[101], PTEXT[101], RTEXT[278], + SETUP = 0, TABSIZ = 330; +char INLINE[101], MAP1[129], MAP2[129]; + +long ABBNUM, ACTSPK[36], AMBER, ATTACK, AXE, BACK, BATTER, BEAR, BIRD, BLOOD, BONUS, + BOTTLE, CAGE, CAVE, CAVITY, CHAIN, CHASM, CHEST, CHLOC, CHLOC2, + CLAM, CLOCK1, CLOCK2, CLOSED, CLOSNG, CLSHNT, CLSMAX = 12, CLSSES, + COINS, COND[186], CONDS, CTEXT[13], CVAL[13], DALTLC, DETAIL, + DKILL, DOOR, DPRSSN, DRAGON, DSEEN[7], DTOTAL, DWARF, EGGS, + EMRALD, ENTER, ENTRNC, FIND, FISSUR, FIXD[101], FOOBAR, FOOD, + GRATE, HINT, HINTED[21], HINTLC[21], HINTS[21][5], HNTMAX, + HNTSIZ = 20, I, INVENT, IGO, IWEST, J, JADE, K, K2, KEY[186], KEYS, KK, + KNFLOC, KNIFE, KQ, L, LAMP, LIMIT, LINSIZ = 12500, LINUSE, LL, + LMWARN, LOC, LOCK, LOCSIZ = 185, LOCSND[186], LOOK, LTEXT[186], + MAGZIN, MAXDIE, MAXTRS, MESH = 123456789, + MESSAG, MIRROR, MXSCOR, + NEWLOC, NOVICE, NUGGET, NUL, NUMDIE, OBJ, OBJSND[101], + OBJTXT[101], ODLOC[7], OGRE, OIL, OLDLC2, OLDLOC, OLDOBJ, OYSTER, + PANIC, PEARL, PILLOW, PLAC[101], PLANT, PLANT2, PROP[101], PYRAM, + RESER, ROD, ROD2, RTXSIZ = 277, RUBY, RUG, SAPPH, SAVED, SAY, + SCORE, SECT, SIGN, SNAKE, SPK, STEPS, STEXT[186], STICK, + STREAM, TABNDX, TALLY, THRESH, THROW, TK[21], TRAVEL[886], TRIDNT, + TRNDEX, TRNLUZ, TRNSIZ = 5, TRNVAL[6], TRNVLS, TROLL, TROLL2, TRVS, + TRVSIZ = 885, TTEXT[6], TURNS, URN, V1, V2, VASE, VEND, VERB, + VOLCAN, VRBSIZ = 35, VRSION = 25, WATER, WD1, WD1X, WD2, WD2X, + WZDARK = FALSE, ZZWORD; + +extern initialise(); +extern void score(long); +extern action(long); + +/* + * MAIN PROGRAM + */ + +main() { + +/* ADVENTURE (REV 2: 20 TREASURES) */ + +/* HISTORY: ORIGINAL IDEA & 5-TREASURE VERSION (ADVENTURES) BY WILLIE CROWTHER + * 15-TREASURE VERSION (ADVENTURE) BY DON WOODS, APRIL-JUNE 1977 + * 20-TREASURE VERSION (REV 2) BY DON WOODS, AUGUST 1978 + * ERRATA FIXED: 78/12/25 */ + + +/* LOGICAL VARIABLES: + * + * CLOSED SAYS WHETHER WE'RE ALL THE WAY CLOSED + * CLOSNG SAYS WHETHER IT'S CLOSING TIME YET + * CLSHNT SAYS WHETHER HE'S READ THE CLUE IN THE ENDGAME + * LMWARN SAYS WHETHER HE'S BEEN WARNED ABOUT LAMP GOING DIM + * NOVICE SAYS WHETHER HE ASKED FOR INSTRUCTIONS AT START-UP + * PANIC SAYS WHETHER HE'S FOUND OUT HE'S TRAPPED IN THE CAVE + * WZDARK SAYS WHETHER THE LOC HE'S LEAVING WAS DARK */ + +#include "funcs.h" + +/* READ THE DATABASE IF WE HAVE NOT YET DONE SO */ + + LINES = (long *)calloc(LINSIZ+1,sizeof(long)); + if(!LINES){ + printf("Not enough memory!\n"); + exit(FALSE); + } + + MAP2[1] = 0; + if(!SETUP)initialise(); + if(SETUP > 0) goto L1; + +/* UNLIKE EARLIER VERSIONS, ADVENTURE IS NO LONGER RESTARTABLE. (THIS + * LETS US GET AWAY WITH MODIFYING THINGS SUCH AS OBJSND(BIRD) WITHOUT + * HAVING TO BE ABLE TO UNDO THE CHANGES LATER.) IF A "USED" COPY IS + * RERUN, WE COME HERE AND TELL THE PLAYER TO RUN A FRESH COPY. */ + + RSPEAK(201); + exit(FALSE); + + + +/* START-UP, DWARF STUFF */ + +L1: SETUP= -1; + I=RAN(-1); + ZZWORD=RNDVOC(3,0)+MESH*2; + NOVICE=YES(65,1,0); + NEWLOC=1; + LOC=1; + LIMIT=330; + if(NOVICE)LIMIT=1000; + +/* CAN'T LEAVE CAVE ONCE IT'S CLOSING (EXCEPT BY MAIN OFFICE). */ + +L2: if(!OUTSID(NEWLOC) || NEWLOC == 0 || !CLOSNG) goto L71; + RSPEAK(130); + NEWLOC=LOC; + if(!PANIC)CLOCK2=15; + PANIC=TRUE; + +/* SEE IF A DWARF HAS SEEN HIM AND HAS COME FROM WHERE HE WANTS TO GO. IF SO, + * THE DWARF'S BLOCKING HIS WAY. IF COMING FROM PLACE FORBIDDEN TO PIRATE + * (DWARVES ROOTED IN PLACE) LET HIM GET OUT (AND ATTACKED). */ + +L71: if(NEWLOC == LOC || FORCED(LOC) || CNDBIT(LOC,3)) goto L74; + /* 73 */ for (I=1; I<=5; I++) { + if(ODLOC[I] != NEWLOC || !DSEEN[I]) goto L73; + NEWLOC=LOC; + RSPEAK(2); + goto L74; +L73: /*etc*/ ; + } /* end loop */ +L74: LOC=NEWLOC; + +/* DWARF STUFF. SEE EARLIER COMMENTS FOR DESCRIPTION OF VARIABLES. REMEMBER + * SIXTH DWARF IS PIRATE AND IS THUS VERY DIFFERENT EXCEPT FOR MOTION RULES. */ + +/* FIRST OFF, DON'T LET THE DWARVES FOLLOW HIM INTO A PIT OR A WALL. ACTIVATE + * THE WHOLE MESS THE FIRST TIME HE GETS AS FAR AS THE HALL OF MISTS (LOC 15). + * IF NEWLOC IS FORBIDDEN TO PIRATE (IN PARTICULAR, IF IT'S BEYOND THE TROLL + * BRIDGE), BYPASS DWARF STUFF. THAT WAY PIRATE CAN'T STEAL RETURN TOLL, AND + * DWARVES CAN'T MEET THE BEAR. ALSO MEANS DWARVES WON'T FOLLOW HIM INTO DEAD + * END IN MAZE, BUT C'EST LA VIE. THEY'LL WAIT FOR HIM OUTSIDE THE DEAD END. */ + + if(LOC == 0 || FORCED(LOC) || CNDBIT(NEWLOC,3)) goto L2000; + if(DFLAG != 0) goto L6000; + if(INDEEP(LOC))DFLAG=1; + goto L2000; + +/* WHEN WE ENCOUNTER THE FIRST DWARF, WE KILL 0, 1, OR 2 OF THE 5 DWARVES. IF + * ANY OF THE SURVIVORS IS AT LOC, REPLACE HIM WITH THE ALTERNATE. */ + +L6000: if(DFLAG != 1) goto L6010; + if(!INDEEP(LOC) || (PCT(95) && (!CNDBIT(LOC,4) || PCT(85)))) goto L2000; + DFLAG=2; + /* 6001 */ for (I=1; I<=2; I++) { + J=1+RAN(5); +L6001: if(PCT(50))DLOC[J]=0; + } /* end loop */ + /* 6002 */ for (I=1; I<=5; I++) { + if(DLOC[I] == LOC)DLOC[I]=DALTLC; +L6002: ODLOC[I]=DLOC[I]; + } /* end loop */ + RSPEAK(3); + DROP(AXE,LOC); + goto L2000; + +/* THINGS ARE IN FULL SWING. MOVE EACH DWARF AT RANDOM, EXCEPT IF HE'S SEEN US + * HE STICKS WITH US. DWARVES STAY DEEP INSIDE. IF WANDERING AT RANDOM, + * THEY DON'T BACK UP UNLESS THERE'S NO ALTERNATIVE. IF THEY DON'T HAVE TO + * MOVE, THEY ATTACK. AND, OF COURSE, DEAD DWARVES DON'T DO MUCH OF ANYTHING. */ + +L6010: DTOTAL=0; + ATTACK=0; + STICK=0; + /* 6030 */ for (I=1; I<=6; I++) { + if(DLOC[I] == 0) goto L6030; +/* FILL TK ARRAY WITH ALL THE PLACES THIS DWARF MIGHT GO. */ + J=1; + KK=DLOC[I]; + KK=KEY[KK]; + if(KK == 0) goto L6016; +L6012: NEWLOC=MOD(IABS(TRAVEL[KK])/1000,1000); + {long x = J-1; + if(NEWLOC > 300 || !INDEEP(NEWLOC) || NEWLOC == ODLOC[I] || (J > 1 && + NEWLOC == TK[x]) || J >= 20 || NEWLOC == DLOC[I] || + FORCED(NEWLOC) || (I == 6 && CNDBIT(NEWLOC,3)) || + IABS(TRAVEL[KK])/1000000 == 100) goto L6014;} + TK[J]=NEWLOC; + J=J+1; +L6014: KK=KK+1; + {long x = KK-1; if(TRAVEL[x] >= 0) goto L6012;} +L6016: TK[J]=ODLOC[I]; + if(J >= 2)J=J-1; + J=1+RAN(J); + ODLOC[I]=DLOC[I]; + DLOC[I]=TK[J]; + DSEEN[I]=(DSEEN[I] && INDEEP(LOC)) || (DLOC[I] == LOC || ODLOC[I] == LOC); + if(!DSEEN[I]) goto L6030; + DLOC[I]=LOC; + if(I != 6) goto L6027; + +/* THE PIRATE'S SPOTTED HIM. HE LEAVES HIM ALONE ONCE WE'VE FOUND CHEST. K + * COUNTS IF A TREASURE IS HERE. IF NOT, AND TALLY=1 FOR AN UNSEEN CHEST, LET + * THE PIRATE BE SPOTTED. NOTE THAT PLACE(CHEST)=0 MIGHT MEAN THAT HE'S + * THROWN IT TO THE TROLL, BUT IN THAT CASE HE'S SEEN THE CHEST (PROP=0). */ + + if(LOC == CHLOC || PROP[CHEST] >= 0) goto L6030; + K=0; + /* 6020 */ for (J=50; J<=MAXTRS; J++) { +/* PIRATE WON'T TAKE PYRAMID FROM PLOVER ROOM OR DARK ROOM (TOO EASY!). */ + if(J == PYRAM && (LOC == PLAC[PYRAM] || LOC == PLAC[EMRALD])) goto L6020; + if(TOTING(J)) goto L6021; +L6020: if(HERE(J))K=1; + } /* end loop */ + if(TALLY == 1 && K == 0 && PLACE[CHEST] == 0 && HERE(LAMP) && PROP[LAMP] + == 1) goto L6025; + if(ODLOC[6] != DLOC[6] && PCT(20))RSPEAK(127); + goto L6030; + +L6021: if(PLACE[CHEST] != 0) goto L6022; +/* INSTALL CHEST ONLY ONCE, TO INSURE IT IS THE LAST TREASURE IN THE LIST. */ + MOVE(CHEST,CHLOC); + MOVE(MESSAG,CHLOC2); +L6022: RSPEAK(128); + /* 6023 */ for (J=50; J<=MAXTRS; J++) { + if(J == PYRAM && (LOC == PLAC[PYRAM] || LOC == PLAC[EMRALD])) goto L6023; + if(AT(J) && FIXED[J] == 0)CARRY(J,LOC); + if(TOTING(J))DROP(J,CHLOC); +L6023: /*etc*/ ; + } /* end loop */ +L6024: DLOC[6]=CHLOC; + ODLOC[6]=CHLOC; + DSEEN[6]=FALSE; + goto L6030; + +L6025: RSPEAK(186); + MOVE(CHEST,CHLOC); + MOVE(MESSAG,CHLOC2); + goto L6024; + +/* THIS THREATENING LITTLE DWARF IS IN THE ROOM WITH HIM! */ + +L6027: DTOTAL=DTOTAL+1; + if(ODLOC[I] != DLOC[I]) goto L6030; + ATTACK=ATTACK+1; + if(KNFLOC >= 0)KNFLOC=LOC; + if(RAN(1000) < 95*(DFLAG-2))STICK=STICK+1; +L6030: /*etc*/ ; + } /* end loop */ + +/* NOW WE KNOW WHAT'S HAPPENING. LET'S TELL THE POOR SUCKER ABOUT IT. + * NOTE THAT VARIOUS OF THE "KNIFE" MESSAGES MUST HAVE SPECIFIC RELATIVE + * POSITIONS IN THE RSPEAK DATABASE. */ + + if(DTOTAL == 0) goto L2000; + SETPRM(1,DTOTAL,0); + RSPEAK(4+1/DTOTAL); + if(ATTACK == 0) goto L2000; + if(DFLAG == 2)DFLAG=3; + SETPRM(1,ATTACK,0); + K=6; + if(ATTACK > 1)K=250; + RSPEAK(K); + SETPRM(1,STICK,0); + RSPEAK(K+1+2/(1+STICK)); + if(STICK == 0) goto L2000; + OLDLC2=LOC; + goto L99; + + + + + + +/* DESCRIBE THE CURRENT LOCATION AND (MAYBE) GET NEXT COMMAND. */ + +/* PRINT TEXT FOR CURRENT LOC. */ + +L2000: if(LOC == 0) goto L99; + KK=STEXT[LOC]; + if(MOD(ABB[LOC],ABBNUM) == 0 || KK == 0)KK=LTEXT[LOC]; + if(FORCED(LOC) || !DARK(0)) goto L2001; + if(WZDARK && PCT(35)) goto L90; + KK=RTEXT[16]; +L2001: if(TOTING(BEAR))RSPEAK(141); + SPEAK(KK); + K=1; + if(FORCED(LOC)) goto L8; + if(LOC == 33 && PCT(25) && !CLOSNG)RSPEAK(7); + +/* PRINT OUT DESCRIPTIONS OF OBJECTS AT THIS LOCATION. IF NOT CLOSING AND + * PROPERTY VALUE IS NEGATIVE, TALLY OFF ANOTHER TREASURE. RUG IS SPECIAL + * CASE; ONCE SEEN, ITS PROP IS 1 (DRAGON ON IT) TILL DRAGON IS KILLED. + * SIMILARLY FOR CHAIN; PROP IS INITIALLY 1 (LOCKED TO BEAR). THESE HACKS + * ARE BECAUSE PROP=0 IS NEEDED TO GET FULL SCORE. */ + + if(DARK(0)) goto L2012; + ABB[LOC]=ABB[LOC]+1; + I=ATLOC[LOC]; +L2004: if(I == 0) goto L2012; + OBJ=I; + if(OBJ > 100)OBJ=OBJ-100; + if(OBJ == STEPS && TOTING(NUGGET)) goto L2008; + if(PROP[OBJ] >= 0) goto L2006; + if(CLOSED) goto L2008; + PROP[OBJ]=0; + if(OBJ == RUG || OBJ == CHAIN)PROP[OBJ]=1; + TALLY=TALLY-1; +/* NOTE: THERE USED TO BE A TEST HERE TO SEE WHETHER THE PLAYER HAD BLOWN IT + * SO BADLY THAT HE COULD NEVER EVER SEE THE REMAINING TREASURES, AND IF SO + * THE LAMP WAS ZAPPED TO 35 TURNS. BUT THE TESTS WERE TOO SIMPLE-MINDED; + * THINGS LIKE KILLING THE BIRD BEFORE THE SNAKE WAS GONE (CAN NEVER SEE + * JEWELRY), AND DOING IT "RIGHT" WAS HOPELESS. E.G., COULD CROSS TROLL + * BRIDGE SEVERAL TIMES, USING UP ALL AVAILABLE TREASURES, BREAKING VASE, + * USING COINS TO BUY BATTERIES, ETC., AND EVENTUALLY NEVER BE ABLE TO GET + * ACROSS AGAIN. IF BOTTLE WERE LEFT ON FAR SIDE, COULD THEN NEVER GET EGGS + * OR TRIDENT, AND THE EFFECTS PROPAGATE. SO THE WHOLE THING WAS FLUSHED. + * ANYONE WHO MAKES SUCH A GROSS BLUNDER ISN'T LIKELY TO FIND EVERYTHING + * ELSE ANYWAY (SO GOES THE RATIONALISATION). */ +L2006: KK=PROP[OBJ]; + if(OBJ == STEPS && LOC == FIXED[STEPS])KK=1; + PSPEAK(OBJ,KK); +L2008: I=LINK[I]; + goto L2004; + +L2009: K=54; +L2010: SPK=K; +L2011: RSPEAK(SPK); + +L2012: VERB=0; + OLDOBJ=OBJ; + OBJ=0; + +/* CHECK IF THIS LOC IS ELIGIBLE FOR ANY HINTS. IF BEEN HERE LONG ENOUGH, + * BRANCH TO HELP SECTION (ON LATER PAGE). HINTS ALL COME BACK HERE EVENTUALLY + * TO FINISH THE LOOP. IGNORE "HINTS" < 4 (SPECIAL STUFF, SEE DATABASE NOTES). + */ + +L2600: if(COND[LOC] < CONDS) goto L2603; + /* 2602 */ for (HINT=1; HINT<=HNTMAX; HINT++) { + if(HINTED[HINT]) goto L2602; + if(!CNDBIT(LOC,HINT+10))HINTLC[HINT]= -1; + HINTLC[HINT]=HINTLC[HINT]+1; + if(HINTLC[HINT] >= HINTS[HINT][1]) goto L40000; +L2602: /*etc*/ ; + } /* end loop */ + +/* KICK THE RANDOM NUMBER GENERATOR JUST TO ADD VARIETY TO THE CHASE. ALSO, + * IF CLOSING TIME, CHECK FOR ANY OBJECTS BEING TOTED WITH PROP < 0 AND SET + * THE PROP TO -1-PROP. THIS WAY OBJECTS WON'T BE DESCRIBED UNTIL THEY'VE + * BEEN PICKED UP AND PUT DOWN SEPARATE FROM THEIR RESPECTIVE PILES. DON'T + * TICK CLOCK1 UNLESS WELL INTO CAVE (AND NOT AT Y2). */ + +L2603: if(!CLOSED) goto L2605; + if(PROP[OYSTER] < 0 && TOTING(OYSTER))PSPEAK(OYSTER,1); + /* 2604 */ for (I=1; I<=100; I++) { +L2604: if(TOTING(I) && PROP[I] < 0)PROP[I]= -1-PROP[I]; + } /* end loop */ +L2605: WZDARK=DARK(0); + if(KNFLOC > 0 && KNFLOC != LOC)KNFLOC=0; + I=RAN(1); + GETIN(WD1,WD1X,WD2,WD2X); + +/* EVERY INPUT, CHECK "FOOBAR" FLAG. IF ZERO, NOTHING'S GOING ON. IF POS, + * MAKE NEG. IF NEG, HE SKIPPED A WORD, SO MAKE IT ZERO. */ + +L2607: FOOBAR=(FOOBAR>0 ? -FOOBAR : 0); + TURNS=TURNS+1; + if(TURNS != THRESH) goto L2608; + SPEAK(TTEXT[TRNDEX]); + TRNLUZ=TRNLUZ+TRNVAL[TRNDEX]/100000; + TRNDEX=TRNDEX+1; + THRESH= -1; + if(TRNDEX <= TRNVLS)THRESH=MOD(TRNVAL[TRNDEX],100000)+1; +L2608: if(VERB == SAY && WD2 > 0)VERB=0; + if(VERB == SAY) goto L4090; + if(TALLY == 0 && INDEEP(LOC) && LOC != 33)CLOCK1=CLOCK1-1; + if(CLOCK1 == 0) goto L10000; + if(CLOCK1 < 0)CLOCK2=CLOCK2-1; + if(CLOCK2 == 0) goto L11000; + if(PROP[LAMP] == 1)LIMIT=LIMIT-1; + if(LIMIT <= 30 && HERE(BATTER) && PROP[BATTER] == 0 && HERE(LAMP)) goto + L12000; + if(LIMIT == 0) goto L12400; + if(LIMIT <= 30) goto L12200; +L19999: K=43; + if(LIQLOC(LOC) == WATER)K=70; + V1=VOCAB(WD1,-1); + V2=VOCAB(WD2,-1); + if(V1 == ENTER && (V2 == STREAM || V2 == 1000+WATER)) goto L2010; + if(V1 == ENTER && WD2 > 0) goto L2800; + if((V1 != 1000+WATER && V1 != 1000+OIL) || (V2 != 1000+PLANT && V2 != + 1000+DOOR)) goto L2610; + {long x = V2-1000; if(AT(x))WD2=MAKEWD(16152118);} +L2610: if(V1 == 1000+CAGE && V2 == 1000+BIRD && HERE(CAGE) && + HERE(BIRD))WD1=MAKEWD(301200308); +L2620: if(WD1 != MAKEWD(23051920)) goto L2625; + IWEST=IWEST+1; + if(IWEST == 10)RSPEAK(17); +L2625: if(WD1 != MAKEWD( 715) || WD2 == 0) goto L2630; + IGO=IGO+1; + if(IGO == 10)RSPEAK(276); +L2630: I=VOCAB(WD1,-1); + if(I == -1) goto L3000; + K=MOD(I,1000); + KQ=I/1000+1; + switch (KQ-1) { case 0: goto L8; case 1: goto L5000; case 2: goto L4000; + case 3: goto L2010; } + BUG(22); + +/* GET SECOND WORD FOR ANALYSIS. */ + +L2800: WD1=WD2; + WD1X=WD2X; + WD2=0; + goto L2620; + +/* GEE, I DON'T UNDERSTAND. */ + +L3000: SETPRM(1,WD1,WD1X); + RSPEAK(254); + goto L2600; + +/* VERB AND OBJECT ANALYSIS MOVED TO SEPARATE MODULE. */ + +L4000: I=4000; goto Laction; +L4090: I=4090; goto Laction; +L5000: I=5000; +Laction: + switch (action(I)) { + case 2: goto L2; + case 8: goto L8; + case 2000: goto L2000; + case 2009: goto L2009; + case 2010: goto L2010; + case 2011: goto L2011; + case 2012: goto L2012; + case 2600: goto L2600; + case 2607: goto L2607; + case 2630: goto L2630; + case 2800: goto L2800; + case 8000: goto L8000; + case 18999: goto L18999; + case 19000: goto L19000; + } + BUG(99); + +/* RANDOM INTRANSITIVE VERBS COME HERE. CLEAR OBJ JUST IN CASE (SEE "ATTACK"). + */ + +L8000: SETPRM(1,WD1,WD1X); + RSPEAK(257); + OBJ=0; + goto L2600; + +/* FIGURE OUT THE NEW LOCATION + * + * GIVEN THE CURRENT LOCATION IN "LOC", AND A MOTION VERB NUMBER IN "K", PUT + * THE NEW LOCATION IN "NEWLOC". THE CURRENT LOC IS SAVED IN "OLDLOC" IN CASE + * HE WANTS TO RETREAT. THE CURRENT OLDLOC IS SAVED IN OLDLC2, IN CASE HE + * DIES. (IF HE DOES, NEWLOC WILL BE LIMBO, AND OLDLOC WILL BE WHAT KILLED + * HIM, SO WE NEED OLDLC2, WHICH IS THE LAST PLACE HE WAS SAFE.) */ + +L8: KK=KEY[LOC]; + NEWLOC=LOC; + if(KK == 0)BUG(26); + if(K == NUL) goto L2; + if(K == BACK) goto L20; + if(K == LOOK) goto L30; + if(K == CAVE) goto L40; + OLDLC2=OLDLOC; + OLDLOC=LOC; + +L9: LL=IABS(TRAVEL[KK]); + if(MOD(LL,1000) == 1 || MOD(LL,1000) == K) goto L10; + if(TRAVEL[KK] < 0) goto L50; + KK=KK+1; + goto L9; + +L10: LL=LL/1000; +L11: NEWLOC=LL/1000; + K=MOD(NEWLOC,100); + if(NEWLOC <= 300) goto L13; + if(PROP[K] != NEWLOC/100-3) goto L16; +L12: if(TRAVEL[KK] < 0)BUG(25); + KK=KK+1; + NEWLOC=IABS(TRAVEL[KK])/1000; + if(NEWLOC == LL) goto L12; + LL=NEWLOC; + goto L11; + +L13: if(NEWLOC <= 100) goto L14; + if(TOTING(K) || (NEWLOC > 200 && AT(K))) goto L16; + goto L12; + +L14: if(NEWLOC != 0 && !PCT(NEWLOC)) goto L12; +L16: NEWLOC=MOD(LL,1000); + if(NEWLOC <= 300) goto L2; + if(NEWLOC <= 500) goto L30000; + RSPEAK(NEWLOC-500); + NEWLOC=LOC; + goto L2; + +/* SPECIAL MOTIONS COME HERE. LABELLING CONVENTION: STATEMENT NUMBERS NNNXX + * (XX=00-99) ARE USED FOR SPECIAL CASE NUMBER NNN (NNN=301-500). */ + +L30000: NEWLOC=NEWLOC-300; + switch (NEWLOC) { case 1: goto L30100; case 2: goto L30200; case 3: goto + L30300; } + BUG(20); + +/* TRAVEL 301. PLOVER-ALCOVE PASSAGE. CAN CARRY ONLY EMERALD. NOTE: TRAVEL + * TABLE MUST INCLUDE "USELESS" ENTRIES GOING THROUGH PASSAGE, WHICH CAN NEVER + * BE USED FOR ACTUAL MOTION, BUT CAN BE SPOTTED BY "GO BACK". */ + +L30100: NEWLOC=99+100-LOC; + if(HOLDNG == 0 || (HOLDNG == 1 && TOTING(EMRALD))) goto L2; + NEWLOC=LOC; + RSPEAK(117); + goto L2; + +/* TRAVEL 302. PLOVER TRANSPORT. DROP THE EMERALD (ONLY USE SPECIAL TRAVEL IF + * TOTING IT), SO HE'S FORCED TO USE THE PLOVER-PASSAGE TO GET IT OUT. HAVING + * DROPPED IT, GO BACK AND PRETEND HE WASN'T CARRYING IT AFTER ALL. */ + +L30200: DROP(EMRALD,LOC); + goto L12; + +/* TRAVEL 303. TROLL BRIDGE. MUST BE DONE ONLY AS SPECIAL MOTION SO THAT + * DWARVES WON'T WANDER ACROSS AND ENCOUNTER THE BEAR. (THEY WON'T FOLLOW THE + * PLAYER THERE BECAUSE THAT REGION IS FORBIDDEN TO THE PIRATE.) IF + * PROP(TROLL)=1, HE'S CROSSED SINCE PAYING, SO STEP OUT AND BLOCK HIM. + * (STANDARD TRAVEL ENTRIES CHECK FOR PROP(TROLL)=0.) SPECIAL STUFF FOR BEAR. */ + +L30300: if(PROP[TROLL] != 1) goto L30310; + PSPEAK(TROLL,1); + PROP[TROLL]=0; + MOVE(TROLL2,0); + MOVE(TROLL2+100,0); + MOVE(TROLL,PLAC[TROLL]); + MOVE(TROLL+100,FIXD[TROLL]); + JUGGLE(CHASM); + NEWLOC=LOC; + goto L2; + +L30310: NEWLOC=PLAC[TROLL]+FIXD[TROLL]-LOC; + if(PROP[TROLL] == 0)PROP[TROLL]=1; + if(!TOTING(BEAR)) goto L2; + RSPEAK(162); + PROP[CHASM]=1; + PROP[TROLL]=2; + DROP(BEAR,NEWLOC); + FIXED[BEAR]= -1; + PROP[BEAR]=3; + OLDLC2=NEWLOC; + goto L99; + +/* END OF SPECIALS. */ + +/* HANDLE "GO BACK". LOOK FOR VERB WHICH GOES FROM LOC TO OLDLOC, OR TO OLDLC2 + * IF OLDLOC HAS FORCED-MOTION. K2 SAVES ENTRY -> FORCED LOC -> PREVIOUS LOC. */ + +L20: K=OLDLOC; + if(FORCED(K))K=OLDLC2; + OLDLC2=OLDLOC; + OLDLOC=LOC; + K2=0; + if(K == LOC)K2=91; + if(CNDBIT(LOC,4))K2=274; + if(K2 == 0) goto L21; + RSPEAK(K2); + goto L2; + +L21: LL=MOD((IABS(TRAVEL[KK])/1000),1000); + if(LL == K) goto L25; + if(LL > 300) goto L22; + J=KEY[LL]; + if(FORCED(LL) && MOD((IABS(TRAVEL[J])/1000),1000) == K)K2=KK; +L22: if(TRAVEL[KK] < 0) goto L23; + KK=KK+1; + goto L21; + +L23: KK=K2; + if(KK != 0) goto L25; + RSPEAK(140); + goto L2; + +L25: K=MOD(IABS(TRAVEL[KK]),1000); + KK=KEY[LOC]; + goto L9; + +/* LOOK. CAN'T GIVE MORE DETAIL. PRETEND IT WASN'T DARK (THOUGH IT MAY "NOW" + * BE DARK) SO HE WON'T FALL INTO A PIT WHILE STARING INTO THE GLOOM. */ + +L30: if(DETAIL < 3)RSPEAK(15); + DETAIL=DETAIL+1; + WZDARK=FALSE; + ABB[LOC]=0; + goto L2; + +/* CAVE. DIFFERENT MESSAGES DEPENDING ON WHETHER ABOVE GROUND. */ + +L40: K=58; + if(OUTSID(LOC) && LOC != 8)K=57; + RSPEAK(K); + goto L2; + +/* NON-APPLICABLE MOTION. VARIOUS MESSAGES DEPENDING ON WORD GIVEN. */ + +L50: SPK=12; + if(K >= 43 && K <= 50)SPK=52; + if(K == 29 || K == 30)SPK=52; + if(K == 7 || K == 36 || K == 37)SPK=10; + if(K == 11 || K == 19)SPK=11; + if(VERB == FIND || VERB == INVENT)SPK=59; + if(K == 62 || K == 65)SPK=42; + if(K == 17)SPK=80; + RSPEAK(SPK); + goto L2; + + + + + +/* "YOU'RE DEAD, JIM." + * + * IF THE CURRENT LOC IS ZERO, IT MEANS THE CLOWN GOT HIMSELF KILLED. WE'LL + * ALLOW THIS MAXDIE TIMES. MAXDIE IS AUTOMATICALLY SET BASED ON THE NUMBER OF + * SNIDE MESSAGES AVAILABLE. EACH DEATH RESULTS IN A MESSAGE (81, 83, ETC.) + * WHICH OFFERS REINCARNATION; IF ACCEPTED, THIS RESULTS IN MESSAGE 82, 84, + * ETC. THE LAST TIME, IF HE WANTS ANOTHER CHANCE, HE GETS A SNIDE REMARK AS + * WE EXIT. WHEN REINCARNATED, ALL OBJECTS BEING CARRIED GET DROPPED AT OLDLC2 + * (PRESUMABLY THE LAST PLACE PRIOR TO BEING KILLED) WITHOUT CHANGE OF PROPS. + * THE LOOP RUNS BACKWARDS TO ASSURE THAT THE BIRD IS DROPPED BEFORE THE CAGE. + * (THIS KLUGE COULD BE CHANGED ONCE WE'RE SURE ALL REFERENCES TO BIRD AND CAGE + * ARE DONE BY KEYWORDS.) THE LAMP IS A SPECIAL CASE (IT WOULDN'T DO TO LEAVE + * IT IN THE CAVE). IT IS TURNED OFF AND LEFT OUTSIDE THE BUILDING (ONLY IF HE + * WAS CARRYING IT, OF COURSE). HE HIMSELF IS LEFT INSIDE THE BUILDING (AND + * HEAVEN HELP HIM IF HE TRIES TO XYZZY BACK INTO THE CAVE WITHOUT THE LAMP!). + * OLDLOC IS ZAPPED SO HE CAN'T JUST "RETREAT". */ + +/* THE EASIEST WAY TO GET KILLED IS TO FALL INTO A PIT IN PITCH DARKNESS. */ + +L90: RSPEAK(23); + OLDLC2=LOC; + +/* OKAY, HE'S DEAD. LET'S GET ON WITH IT. */ + +L99: if(CLOSNG) goto L95; + NUMDIE=NUMDIE+1; + if(!YES(79+NUMDIE*2,80+NUMDIE*2,54)) score(0); + if(NUMDIE == MAXDIE) score(0); + PLACE[WATER]=0; + PLACE[OIL]=0; + if(TOTING(LAMP))PROP[LAMP]=0; + /* 98 */ for (J=1; J<=100; J++) { + I=101-J; + if(!TOTING(I)) goto L98; + K=OLDLC2; + if(I == LAMP)K=1; + DROP(I,K); +L98: /*etc*/ ; + } /* end loop */ + LOC=3; + OLDLOC=LOC; + goto L2000; + +/* HE DIED DURING CLOSING TIME. NO RESURRECTION. TALLY UP A DEATH AND EXIT. */ + +L95: RSPEAK(131); + NUMDIE=NUMDIE+1; + score(0); + + + + +/* HINTS */ + +/* COME HERE IF HE'S BEEN LONG ENOUGH AT REQUIRED LOC(S) FOR SOME UNUSED HINT. + * HINT NUMBER IS IN VARIABLE "HINT". BRANCH TO QUICK TEST FOR ADDITIONAL + * CONDITIONS, THEN COME BACK TO DO NEAT STUFF. GOTO 40010 IF CONDITIONS ARE + * MET AND WE WANT TO OFFER THE HINT. GOTO 40020 TO CLEAR HINTLC BACK TO ZERO, + * 40030 TO TAKE NO ACTION YET. */ + +L40000: switch (HINT-1) { case 0: goto L40100; case 1: goto L40200; case 2: goto + L40300; case 3: goto L40400; case 4: goto L40500; case 5: goto + L40600; case 6: goto L40700; case 7: goto L40800; case 8: goto + L40900; case 9: goto L41000; } +/* CAVE BIRD SNAKE MAZE DARK WITT URN WOODS OGRE + * JADE */ + BUG(27); + +L40010: HINTLC[HINT]=0; + if(!YES(HINTS[HINT][3],0,54)) goto L2602; + SETPRM(1,HINTS[HINT][2],HINTS[HINT][2]); + RSPEAK(261); + HINTED[HINT]=YES(175,HINTS[HINT][4],54); + if(HINTED[HINT] && LIMIT > 30)LIMIT=LIMIT+30*HINTS[HINT][2]; +L40020: HINTLC[HINT]=0; +L40030: goto L2602; + +/* NOW FOR THE QUICK TESTS. SEE DATABASE DESCRIPTION FOR ONE-LINE NOTES. */ + +L40100: if(PROP[GRATE] == 0 && !HERE(KEYS)) goto L40010; + goto L40020; + +L40200: if(PLACE[BIRD] == LOC && TOTING(ROD) && OLDOBJ == BIRD) goto L40010; + goto L40030; + +L40300: if(HERE(SNAKE) && !HERE(BIRD)) goto L40010; + goto L40020; + +L40400: if(ATLOC[LOC] == 0 && ATLOC[OLDLOC] == 0 && ATLOC[OLDLC2] == 0 && HOLDNG > + 1) goto L40010; + goto L40020; + +L40500: if(PROP[EMRALD] != -1 && PROP[PYRAM] == -1) goto L40010; + goto L40020; + +L40600: goto L40010; + +L40700: if(DFLAG == 0) goto L40010; + goto L40020; + +L40800: if(ATLOC[LOC] == 0 && ATLOC[OLDLOC] == 0 && ATLOC[OLDLC2] == 0) goto + L40010; + goto L40030; + +L40900: I=ATDWRF(LOC); + if(I < 0) goto L40020; + if(HERE(OGRE) && I == 0) goto L40010; + goto L40030; + +L41000: if(TALLY == 1 && PROP[JADE] < 0) goto L40010; + goto L40020; + + + + + +/* CAVE CLOSING AND SCORING */ + + +/* THESE SECTIONS HANDLE THE CLOSING OF THE CAVE. THE CAVE CLOSES "CLOCK1" + * TURNS AFTER THE LAST TREASURE HAS BEEN LOCATED (INCLUDING THE PIRATE'S + * CHEST, WHICH MAY OF COURSE NEVER SHOW UP). NOTE THAT THE TREASURES NEED NOT + * HAVE BEEN TAKEN YET, JUST LOCATED. HENCE CLOCK1 MUST BE LARGE ENOUGH TO GET + * OUT OF THE CAVE (IT ONLY TICKS WHILE INSIDE THE CAVE). WHEN IT HITS ZERO, + * WE BRANCH TO 10000 TO START CLOSING THE CAVE, AND THEN SIT BACK AND WAIT FOR + * HIM TO TRY TO GET OUT. IF HE DOESN'T WITHIN CLOCK2 TURNS, WE CLOSE THE + * CAVE; IF HE DOES TRY, WE ASSUME HE PANICS, AND GIVE HIM A FEW ADDITIONAL + * TURNS TO GET FRANTIC BEFORE WE CLOSE. WHEN CLOCK2 HITS ZERO, WE BRANCH TO + * 11000 TO TRANSPORT HIM INTO THE FINAL PUZZLE. NOTE THAT THE PUZZLE DEPENDS + * UPON ALL SORTS OF RANDOM THINGS. FOR INSTANCE, THERE MUST BE NO WATER OR + * OIL, SINCE THERE ARE BEANSTALKS WHICH WE DON'T WANT TO BE ABLE TO WATER, + * SINCE THE CODE CAN'T HANDLE IT. ALSO, WE CAN HAVE NO KEYS, SINCE THERE IS A + * GRATE (HAVING MOVED THE FIXED OBJECT!) THERE SEPARATING HIM FROM ALL THE + * TREASURES. MOST OF THESE PROBLEMS ARISE FROM THE USE OF NEGATIVE PROP + * NUMBERS TO SUPPRESS THE OBJECT DESCRIPTIONS UNTIL HE'S ACTUALLY MOVED THE + * OBJECTS. */ + +/* WHEN THE FIRST WARNING COMES, WE LOCK THE GRATE, DESTROY THE BRIDGE, KILL + * ALL THE DWARVES (AND THE PIRATE), REMOVE THE TROLL AND BEAR (UNLESS DEAD), + * AND SET "CLOSNG" TO TRUE. LEAVE THE DRAGON; TOO MUCH TROUBLE TO MOVE IT. + * FROM NOW UNTIL CLOCK2 RUNS OUT, HE CANNOT UNLOCK THE GRATE, MOVE TO ANY + * LOCATION OUTSIDE THE CAVE, OR CREATE THE BRIDGE. NOR CAN HE BE + * RESURRECTED IF HE DIES. NOTE THAT THE SNAKE IS ALREADY GONE, SINCE HE GOT + * TO THE TREASURE ACCESSIBLE ONLY VIA THE HALL OF THE MT. KING. ALSO, HE'S + * BEEN IN GIANT ROOM (TO GET EGGS), SO WE CAN REFER TO IT. ALSO ALSO, HE'S + * GOTTEN THE PEARL, SO WE KNOW THE BIVALVE IS AN OYSTER. *AND*, THE DWARVES + * MUST HAVE BEEN ACTIVATED, SINCE WE'VE FOUND CHEST. */ + +L10000: PROP[GRATE]=0; + PROP[FISSUR]=0; + /* 10010 */ for (I=1; I<=6; I++) { + DSEEN[I]=FALSE; +L10010: DLOC[I]=0; + } /* end loop */ + MOVE(TROLL,0); + MOVE(TROLL+100,0); + MOVE(TROLL2,PLAC[TROLL]); + MOVE(TROLL2+100,FIXD[TROLL]); + JUGGLE(CHASM); + if(PROP[BEAR] != 3)DSTROY(BEAR); + PROP[CHAIN]=0; + FIXED[CHAIN]=0; + PROP[AXE]=0; + FIXED[AXE]=0; + RSPEAK(129); + CLOCK1= -1; + CLOSNG=TRUE; + goto L19999; + +/* ONCE HE'S PANICKED, AND CLOCK2 HAS RUN OUT, WE COME HERE TO SET UP THE + * STORAGE ROOM. THE ROOM HAS TWO LOCS, HARDWIRED AS 115 (NE) AND 116 (SW). + * AT THE NE END, WE PLACE EMPTY BOTTLES, A NURSERY OF PLANTS, A BED OF + * OYSTERS, A PILE OF LAMPS, RODS WITH STARS, SLEEPING DWARVES, AND HIM. AT + * THE SW END WE PLACE GRATE OVER TREASURES, SNAKE PIT, COVEY OF CAGED BIRDS, + * MORE RODS, AND PILLOWS. A MIRROR STRETCHES ACROSS ONE WALL. MANY OF THE + * OBJECTS COME FROM KNOWN LOCATIONS AND/OR STATES (E.G. THE SNAKE IS KNOWN TO + * HAVE BEEN DESTROYED AND NEEDN'T BE CARRIED AWAY FROM ITS OLD "PLACE"), + * MAKING THE VARIOUS OBJECTS BE HANDLED DIFFERENTLY. WE ALSO DROP ALL OTHER + * OBJECTS HE MIGHT BE CARRYING (LEST HE HAVE SOME WHICH COULD CAUSE TROUBLE, + * SUCH AS THE KEYS). WE DESCRIBE THE FLASH OF LIGHT AND TRUNDLE BACK. */ + +L11000: PROP[BOTTLE]=PUT(BOTTLE,115,1); + PROP[PLANT]=PUT(PLANT,115,0); + PROP[OYSTER]=PUT(OYSTER,115,0); + OBJTXT[OYSTER]=3; + PROP[LAMP]=PUT(LAMP,115,0); + PROP[ROD]=PUT(ROD,115,0); + PROP[DWARF]=PUT(DWARF,115,0); + LOC=115; + OLDLOC=115; + NEWLOC=115; + +/* LEAVE THE GRATE WITH NORMAL (NON-NEGATIVE) PROPERTY. REUSE SIGN. */ + + I=PUT(GRATE,116,0); + I=PUT(SIGN,116,0); + OBJTXT[SIGN]=OBJTXT[SIGN]+1; + PROP[SNAKE]=PUT(SNAKE,116,1); + PROP[BIRD]=PUT(BIRD,116,1); + PROP[CAGE]=PUT(CAGE,116,0); + PROP[ROD2]=PUT(ROD2,116,0); + PROP[PILLOW]=PUT(PILLOW,116,0); + + PROP[MIRROR]=PUT(MIRROR,115,0); + FIXED[MIRROR]=116; + + /* 11010 */ for (I=1; I<=100; I++) { +L11010: if(TOTING(I))DSTROY(I); + } /* end loop */ + + RSPEAK(132); + CLOSED=TRUE; + goto L2; + +/* ANOTHER WAY WE CAN FORCE AN END TO THINGS IS BY HAVING THE LAMP GIVE OUT. + * WHEN IT GETS CLOSE, WE COME HERE TO WARN HIM. WE GO TO 12000 IF THE LAMP + * AND FRESH BATTERIES ARE HERE, IN WHICH CASE WE REPLACE THE BATTERIES AND + * CONTINUE. 12200 IS FOR OTHER CASES OF LAMP DYING. 12400 IS WHEN IT GOES + * OUT. EVEN THEN, HE CAN EXPLORE OUTSIDE FOR A WHILE IF DESIRED. */ + +L12000: RSPEAK(188); + PROP[BATTER]=1; + if(TOTING(BATTER))DROP(BATTER,LOC); + LIMIT=LIMIT+2500; + LMWARN=FALSE; + goto L19999; + +L12200: if(LMWARN || !HERE(LAMP)) goto L19999; + LMWARN=TRUE; + SPK=187; + if(PLACE[BATTER] == 0)SPK=183; + if(PROP[BATTER] == 1)SPK=189; + RSPEAK(SPK); + goto L19999; + +L12400: LIMIT= -1; + PROP[LAMP]=0; + if(HERE(LAMP))RSPEAK(184); + goto L19999; + +/* OH DEAR, HE'S DISTURBED THE DWARVES. */ + +L18999: RSPEAK(SPK); +L19000: RSPEAK(136); + score(0); +} diff --git a/main.h b/main.h new file mode 100644 index 0000000..575ee97 --- /dev/null +++ b/main.h @@ -0,0 +1,4 @@ +extern long ABB[], ATAB[], ATLOC[], BLKLIN, DFLAG, DLOC[], FIXED[], HOLDNG, + KTAB[], *LINES, LINK[], LNLENG, LNPOSN, + PARMS[], PLACE[], PTEXT[], RTEXT[], TABSIZ; +extern signed char INLINE[], MAP1[], MAP2[]; diff --git a/misc.c b/misc.c new file mode 100644 index 0000000..e3e8320 --- /dev/null +++ b/misc.c @@ -0,0 +1,1019 @@ +#include "main.h" +#include "misc.h" +#include + +#define TRUE (0==0) +#define FALSE (0!=0) + +/* I/O ROUTINES (SPEAK, PSPEAK, RSPEAK, SETPRM, GETIN, YES) */ + +#undef SPEAK +void fSPEAK(N)long N; { +long BLANK, CASE, I, K, L, NEG, NPARMS, PARM, PRMTYP, STATE; + +/* PRINT THE MESSAGE WHICH STARTS AT LINES(N). PRECEDE IT WITH A BLANK LINE + * UNLESS BLKLIN IS FALSE. */ + + + if(N == 0)return; + BLANK=BLKLIN; + K=N; + NPARMS=1; +L10: L=IABS(LINES[K])-1; + K=K+1; + LNLENG=0; + LNPOSN=1; + STATE=0; + /* 20 */ for (I=K; I<=L; I++) { +L20: PUTTXT(LINES[I],STATE,2,I); + } /* end loop */ + LNPOSN=0; +L30: LNPOSN=LNPOSN+1; +L32: if(LNPOSN > LNLENG) goto L40; + if(INLINE[LNPOSN] != 63) goto L30; + {long x = LNPOSN+1; PRMTYP=INLINE[x];} +/* 63 IS A "%"; THE NEXT CHARACTER DETERMINE THE TYPE OF PARAMETER: 1 (!) = + * SUPPRESS MESSAGE COMPLETELY, 29 (S) = NULL IF PARM=1, ELSE 'S' (OPTIONAL + * PLURAL ENDING), 33 (W) = WORD (TWO 30-BIT VALUES) WITH TRAILING SPACES + * SUPPRESSED, 22 (L) OR 31 (U) = WORD BUT MAP TO LOWER/UPPER CASE, 13 (C) = + * WORD IN LOWER CASE WITH FIRST LETTER CAPITALISED, 30 (T) = TEXT ENDING + * WITH A WORD OF -1, 65-73 (1-9) = NUMBER USING THAT MANY CHARACTERS, + * 12 (B) = VARIABLE NUMBER OF BLANKS. */ + if(PRMTYP == 1)return; + if(PRMTYP == 29) goto L320; + if(PRMTYP == 30) goto L340; + if(PRMTYP == 12) goto L360; + if(PRMTYP == 33 || PRMTYP == 22 || PRMTYP == 31 || PRMTYP == 13) goto + L380; + PRMTYP=PRMTYP-64; + if(PRMTYP < 1 || PRMTYP > 9) goto L30; + SHFTXT(LNPOSN+2,PRMTYP-2); + LNPOSN=LNPOSN+PRMTYP; + PARM=IABS(PARMS[NPARMS]); + NEG=0; + if(PARMS[NPARMS] < 0)NEG=9; + /* 390 */ for (I=1; I<=PRMTYP; I++) { + LNPOSN=LNPOSN-1; + INLINE[LNPOSN]=MOD(PARM,10)+64; + if(I == 1 || PARM != 0) goto L390; + INLINE[LNPOSN]=NEG; + NEG=0; +L390: PARM=PARM/10; + } /* end loop */ + LNPOSN=LNPOSN+PRMTYP; +L395: NPARMS=NPARMS+1; + goto L32; + +L320: SHFTXT(LNPOSN+2,-1); + INLINE[LNPOSN]=55; + if(PARMS[NPARMS] == 1)SHFTXT(LNPOSN+1,-1); + goto L395; + +L340: SHFTXT(LNPOSN+2,-2); + STATE=0; + CASE=2; +L345: if(PARMS[NPARMS] < 0) goto L395; + {long x = NPARMS+1; if(PARMS[x] < 0)CASE=0;} + PUTTXT(PARMS[NPARMS],STATE,CASE,0); + NPARMS=NPARMS+1; + goto L345; + +L360: PRMTYP=PARMS[NPARMS]; + SHFTXT(LNPOSN+2,PRMTYP-2); + if(PRMTYP == 0) goto L395; + /* 365 */ for (I=1; I<=PRMTYP; I++) { + INLINE[LNPOSN]=0; +L365: LNPOSN=LNPOSN+1; + } /* end loop */ + goto L395; + +L380: SHFTXT(LNPOSN+2,-2); + STATE=0; + CASE= -1; + if(PRMTYP == 31)CASE=1; + if(PRMTYP == 33)CASE=0; + I=LNPOSN; + PUTTXT(PARMS[NPARMS],STATE,CASE,0); + {long x = NPARMS+1; PUTTXT(PARMS[x],STATE,CASE,0);} + if(PRMTYP == 13 && INLINE[I] >= 37 && INLINE[I] <= + 62)INLINE[I]=INLINE[I]-26; + NPARMS=NPARMS+2; + goto L32; + +L40: if(BLANK)TYPE0(); + BLANK=FALSE; + TYPE(); + K=L+1; + if(LINES[K] >= 0) goto L10; + return; +} + + + +#define SPEAK(N) fSPEAK(N) +#undef PSPEAK +void fPSPEAK(MSG,SKIP)long MSG, SKIP; { +long I, M; + +/* FIND THE SKIP+1ST MESSAGE FROM MSG AND PRINT IT. MSG SHOULD BE THE INDEX OF + * THE INVENTORY MESSAGE FOR OBJECT. (INVEN+N+1 MESSAGE IS PROP=N MESSAGE). */ + + + M=PTEXT[MSG]; + if(SKIP < 0) goto L9; + /* 3 */ for (I=0; I<=SKIP; I++) { +L1: M=IABS(LINES[M]); + if(LINES[M] >= 0) goto L1; +L3: /*etc*/ ; + } /* end loop */ +L9: SPEAK(M); + return; +} + + + +#define PSPEAK(MSG,SKIP) fPSPEAK(MSG,SKIP) +#undef RSPEAK +void fRSPEAK(I)long I; { +; + +/* PRINT THE I-TH "RANDOM" MESSAGE (SECTION 6 OF DATABASE). */ + + + if(I != 0)SPEAK(RTEXT[I]); + return; +} + + + +#define RSPEAK(I) fRSPEAK(I) +#undef SETPRM +void fSETPRM(FIRST,P1,P2)long FIRST, P1, P2; { +; + +/* STORES PARAMETERS INTO THE PRMCOM PARMS ARRAY FOR USE BY SPEAK. P1 AND P2 + * ARE STORED INTO PARMS(FIRST) AND PARMS(FIRST+1). */ + + + if(FIRST >= 25)BUG(29); + PARMS[FIRST]=P1; + {long x = FIRST+1; PARMS[x]=P2;} + return; +} + + + +#define SETPRM(FIRST,P1,P2) fSETPRM(FIRST,P1,P2) +#undef GETIN +#define WORD1 (*wORD1) +#define WORD1X (*wORD1X) +#define WORD2 (*wORD2) +#define WORD2X (*wORD2X) +void fGETIN(wORD1,wORD1X,wORD2,wORD2X)long *wORD1, *wORD1X, *wORD2, *wORD2X; { +long JUNK; + +/* GET A COMMAND FROM THE ADVENTURER. SNARF OUT THE FIRST WORD, PAD IT WITH + * BLANKS, AND RETURN IT IN WORD1. CHARS 6 THRU 10 ARE RETURNED IN WORD1X, IN + * CASE WE NEED TO PRINT OUT THE WHOLE WORD IN AN ERROR MESSAGE. ANY NUMBER OF + * BLANKS MAY FOLLOW THE WORD. IF A SECOND WORD APPEARS, IT IS RETURNED IN + * WORD2 (CHARS 6 THRU 10 IN WORD2X), ELSE WORD2 IS -1. */ + + +L10: if(BLKLIN)TYPE0(); + MAPLIN(FALSE); + WORD1=GETTXT(TRUE,TRUE,TRUE,0); + if(BLKLIN && WORD1 < 0) goto L10; + WORD1X=GETTXT(FALSE,TRUE,TRUE,0); +L12: JUNK=GETTXT(FALSE,TRUE,TRUE,0); + if(JUNK > 0) goto L12; + WORD2=GETTXT(TRUE,TRUE,TRUE,0); + WORD2X=GETTXT(FALSE,TRUE,TRUE,0); +L22: JUNK=GETTXT(FALSE,TRUE,TRUE,0); + if(JUNK > 0) goto L22; + if(GETTXT(TRUE,TRUE,TRUE,0) <= 0)return; + RSPEAK(53); + goto L10; +} + + + +#undef WORD1 +#undef WORD1X +#undef WORD2 +#undef WORD2X +#define GETIN(WORD1,WORD1X,WORD2,WORD2X) fGETIN(&WORD1,&WORD1X,&WORD2,&WORD2X) +#undef YES +long fYES(X,Y,Z)long X, Y, Z; { + +long YES, REPLY, JUNK1, JUNK2, JUNK3; + +/* PRINT MESSAGE X, WAIT FOR YES/NO ANSWER. IF YES, PRINT Y AND RETURN TRUE; + * IF NO, PRINT Z AND RETURN FALSE. */ + +L1: RSPEAK(X); + GETIN(REPLY,JUNK1,JUNK2,JUNK3); + if(REPLY == MAKEWD(250519) || REPLY == MAKEWD(25)) goto L10; + if(REPLY == MAKEWD(1415) || REPLY == MAKEWD(14)) goto L20; + RSPEAK(185); + goto L1; +L10: YES=TRUE; + RSPEAK(Y); + return(YES); +L20: YES=FALSE; + RSPEAK(Z); + return(YES); +} + + + + + +/* LINE-PARSING ROUTINES (GETNUM, GETTXT, MAKEWD, PUTTXT, SHFTXT, TYPE0) + */ + +/* THE ROUTINES ON THIS PAGE HANDLE ALL THE STUFF THAT WOULD NORMALLY BE + * TAKEN CARE OF BY FORMAT STATEMENTS. WE DO IT THIS WAY INSTEAD SO THAT + * WE CAN HANDLE TEXTUAL DATA IN A MACHINE INDEPENDENT FASHION. ALL THE + * MACHINE DEPENDENT I/O STUFF IS ON THE FOLLOWING PAGE. SEE THAT PAGE + * FOR A DESCRIPTION OF MAPCOM'S INLINE ARRAY. */ + +#define YES(X,Y,Z) fYES(X,Y,Z) +#undef GETNUM +long fGETNUM(K)long K; { +long DIGIT, GETNUM, SIGN; + +/* OBTAIN THE NEXT INTEGER FROM AN INPUT LINE. IF K>0, WE FIRST READ A + * NEW INPUT LINE FROM A FILE; IF K<0, WE READ A LINE FROM THE KEYBOARD; + * IF K=0 WE USE A LINE THAT HAS ALREADY BEEN READ (AND PERHAPS PARTIALLY + * SCANNED). IF WE'RE AT THE END OF THE LINE OR ENCOUNTER AN ILLEGAL + * CHARACTER (NOT A DIGIT, HYPHEN, OR BLANK), WE RETURN 0. */ + + + if(K != 0)MAPLIN(K > 0); + GETNUM=0; +L10: if(LNPOSN > LNLENG)return(GETNUM); + if(INLINE[LNPOSN] != 0) goto L20; + LNPOSN=LNPOSN+1; + goto L10; + +L20: SIGN=1; + if(INLINE[LNPOSN] != 9) goto L32; + SIGN= -1; +L30: LNPOSN=LNPOSN+1; +L32: if(LNPOSN > LNLENG || INLINE[LNPOSN] == 0) goto L42; + DIGIT=INLINE[LNPOSN]-64; + if(DIGIT < 0 || DIGIT > 9) goto L40; + GETNUM=GETNUM*10+DIGIT; + goto L30; + +L40: GETNUM=0; +L42: GETNUM=GETNUM*SIGN; + LNPOSN=LNPOSN+1; + return(GETNUM); +} + + + +#define GETNUM(K) fGETNUM(K) +#undef GETTXT +long fGETTXT(SKIP,ONEWRD,UPPER,HASH)long HASH, ONEWRD, SKIP, UPPER; { +long CHAR, GETTXT, I; static long SPLITTING = -1; + +/* TAKE CHARACTERS FROM AN INPUT LINE AND PACK THEM INTO 30-BIT WORDS. + * SKIP SAYS TO SKIP LEADING BLANKS. ONEWRD SAYS STOP IF WE COME TO A + * BLANK. UPPER SAYS TO MAP ALL LETTERS TO UPPERCASE. HASH MAY BE USED + * AS A PARAMETER FOR ENCRYPTING THE TEXT IF DESIRED; HOWEVER, A HASH OF 0 + * SHOULD RESULT IN UNMODIFIED BYTES BEING PACKED. IF WE REACH THE + * END OF THE LINE, THE WORD IS FILLED UP WITH BLANKS (WHICH ENCODE AS 0'S). + * IF WE'RE ALREADY AT END OF LINE WHEN GETTXT IS CALLED, WE RETURN -1. */ + + if(LNPOSN != SPLITTING)SPLITTING = -1; + GETTXT= -1; +L10: if(LNPOSN > LNLENG)return(GETTXT); + if((!SKIP) || INLINE[LNPOSN] != 0) goto L11; + LNPOSN=LNPOSN+1; + goto L10; + +L11: GETTXT=0; + /* 15 */ for (I=1; I<=5; I++) { + GETTXT=GETTXT*64; + if(LNPOSN > LNLENG || (ONEWRD && INLINE[LNPOSN] == 0)) goto L15; + CHAR=INLINE[LNPOSN]; + if(CHAR >= 63) goto L12; + SPLITTING = -1; + if(UPPER && CHAR >= 37)CHAR=CHAR-26; + GETTXT=GETTXT+CHAR; + goto L14; + +L12: if(SPLITTING == LNPOSN) goto L13; + GETTXT=GETTXT+63; + SPLITTING = LNPOSN; + goto L15; + +L13: GETTXT=GETTXT+CHAR-63; + SPLITTING = -1; +L14: LNPOSN=LNPOSN+1; +L15: /*etc*/ ; + } /* end loop */ + + if(HASH)GETTXT=GETTXT+MOD(HASH*13579L+5432L,97531L)*12345L+HASH; + return(GETTXT); +} + + + +#define GETTXT(SKIP,ONEWRD,UPPER,HASH) fGETTXT(SKIP,ONEWRD,UPPER,HASH) +#undef MAKEWD +long fMAKEWD(LETTRS)long LETTRS; { +long I, L, MAKEWD; + +/* COMBINE FIVE UPPERCASE LETTERS (REPRESENTED BY PAIRS OF DECIMAL DIGITS + * IN LETTRS) TO FORM A 30-BIT VALUE MATCHING THE ONE THAT GETTXT WOULD + * RETURN GIVEN THOSE CHARACTERS PLUS TRAILING BLANKS AND HASH=0. CAUTION: + * LETTRS WILL OVERFLOW 31 BITS IF 5-LETTER WORD STARTS WITH V-Z. AS A + * KLUDGEY WORKAROUND, YOU CAN INCREMENT A LETTER BY 5 BY ADDING 50 TO + * THE NEXT PAIR OF DIGITS. */ + + + MAKEWD=0; + I=1; + L=LETTRS; +L10: MAKEWD=MAKEWD+I*(MOD(L,50)+10); + I=I*64; + if(MOD(L,100) > 50)MAKEWD=MAKEWD+I*5; + L=L/100; + if(L != 0) goto L10; + I=64L*64L*64L*64L*64L/I; + MAKEWD=MAKEWD*I; + return(MAKEWD); +} + + + +#define MAKEWD(LETTRS) fMAKEWD(LETTRS) +#undef PUTTXT +#define STATE (*sTATE) +void fPUTTXT(WORD,sTATE,CASE,HASH)long CASE, HASH, *sTATE, WORD; { +long ALPH1, ALPH2, BYTE, DIV, I, W; + +/* UNPACK THE 30-BIT VALUE IN WORD TO OBTAIN UP TO 5 INTEGER-ENCODED CHARS, + * AND STORE THEM IN INLINE STARTING AT LNPOSN. IF LNLENG>=LNPOSN, SHIFT + * EXISTING CHARACTERS TO THE RIGHT TO MAKE ROOM. HASH MUST BE THE SAME + * AS IT WAS WHEN GETTXT CREATED THE 30-BIT WORD. STATE WILL BE ZERO WHEN + * PUTTXT IS CALLED WITH THE FIRST OF A SEQUENCE OF WORDS, BUT IS THEREAFTER + * UNCHANGED BY THE CALLER, SO PUTTXT CAN USE IT TO MAINTAIN STATE ACROSS + * CALLS. LNPOSN AND LNLENG ARE INCREMENTED BY THE NUMBER OF CHARS STORED. + * IF CASE=1, ALL LETTERS ARE MADE UPPERCASE; IF -1, LOWERCASE; IF 0, AS IS. + * ANY OTHER VALUE FOR CASE IS THE SAME AS 0 BUT ALSO CAUSES TRAILING BLANKS + * TO BE INCLUDED (IN ANTICIPATION OF SUBSEQUENT ADDITIONAL TEXT). */ + + + ALPH1=13*CASE+24; + ALPH2=26*IABS(CASE)+ALPH1; + if(IABS(CASE) > 1)ALPH1=ALPH2; +/* ALPH1&2 DEFINE RANGE OF WRONG-CASE CHARS, 11-36 OR 37-62 OR EMPTY. */ + DIV=64L*64L*64L*64L; + W=WORD; + if(HASH)W=W-MOD(HASH*13579L+5432L,97531L)*12345L-HASH; + /* 18 */ for (I=1; I<=5; I++) { + if(W <= 0 && STATE == 0 && IABS(CASE) <= 1)return; + BYTE=W/DIV; + if(STATE != 0 || BYTE != 63) goto L12; + STATE=63; + goto L18; + +L12: SHFTXT(LNPOSN,1); + STATE=STATE+BYTE; + if(STATE < ALPH2 && STATE >= ALPH1)STATE=STATE-26*CASE; + INLINE[LNPOSN]=STATE; + LNPOSN=LNPOSN+1; + STATE=0; +L18: W=(W-BYTE*DIV)*64; + } /* end loop */ + return; +} + + + +#undef STATE +#define PUTTXT(WORD,STATE,CASE,HASH) fPUTTXT(WORD,&STATE,CASE,HASH) +#undef SHFTXT +void fSHFTXT(FROM,DELTA)long DELTA, FROM; { +long I, II, JJ; + +/* MOVE INLINE(N) TO INLINE(N+DELTA) FOR N=FROM,LNLENG. DELTA CAN BE + * NEGATIVE. LNLENG IS UPDATED; LNPOSN IS NOT CHANGED. */ + + + if(LNLENG < FROM || DELTA == 0) goto L2; + /* 1 */ for (I=FROM; I<=LNLENG; I++) { + II=I; + if(DELTA > 0)II=FROM+LNLENG-I; + JJ=II+DELTA; +L1: INLINE[JJ]=INLINE[II]; + } /* end loop */ +L2: LNLENG=LNLENG+DELTA; + return; +} + + + +#define SHFTXT(FROM,DELTA) fSHFTXT(FROM,DELTA) +#undef TYPE0 +void fTYPE0() { +long TEMP; + +/* TYPE A BLANK LINE. THIS PROCEDURE IS PROVIDED AS A CONVENIENCE FOR CALLERS + * WHO OTHERWISE HAVE NO USE FOR MAPCOM. */ + + + TEMP=LNLENG; + LNLENG=0; + TYPE(); + LNLENG=TEMP; + return; +} + + + +#define TYPE0() fTYPE0() + + +/* SUSPEND/RESUME I/O ROUTINES (SAVWDS, SAVARR, SAVWRD) */ + +#undef SAVWDS +void fSAVWDS(W1,W2,W3,W4,W5,W6,W7)long *W1, *W2, *W3, *W4, *W5, *W6, *W7; { +; + +/* WRITE OR READ 7 VARIABLES. SEE SAVWRD. */ + + + SAVWRD(0,(*W1)); + SAVWRD(0,(*W2)); + SAVWRD(0,(*W3)); + SAVWRD(0,(*W4)); + SAVWRD(0,(*W5)); + SAVWRD(0,(*W6)); + SAVWRD(0,(*W7)); + return; +} + + +#define SAVWDS(W1,W2,W3,W4,W5,W6,W7) fSAVWDS(&W1,&W2,&W3,&W4,&W5,&W6,&W7) +#undef SAVARR +void fSAVARR(ARR,N)long ARR[], N; { +long I; + +/* WRITE OR READ AN ARRAY OF N WORDS. SEE SAVWRD. */ + + + /* 1 */ for (I=1; I<=N; I++) { +L1: SAVWRD(0,ARR[I]); + } /* end loop */ + return; +} + + + +#define SAVARR(ARR,N) fSAVARR(ARR,N) +#undef SAVWRD +#define WORD (*wORD) +void fSAVWRD(OP,wORD)long OP, *wORD; { +static long BUF[250], CKSUM = 0, H1, HASH = 0, N = 0, STATE = 0; + +/* IF OP<0, START WRITING A FILE, USING WORD TO INITIALISE ENCRYPTION; SAVE + * WORD IN THE FILE. IF OP>0, START READING A FILE; READ THE FILE TO FIND + * THE VALUE WITH WHICH TO DECRYPT THE REST. IN EITHER CASE, IF A FILE IS + * ALREADY OPEN, FINISH WRITING/READING IT AND DON'T START A NEW ONE. IF OP=0, + * READ/WRITE A SINGLE WORD. WORDS ARE BUFFERED IN CASE THAT MAKES FOR MORE + * EFFICIENT DISK USE. WE ALSO COMPUTE A SIMPLE CHECKSUM TO CATCH ELEMENTARY + * POKING WITHIN THE SAVED FILE. WHEN WE FINISH READING/WRITING THE FILE, + * WE STORE ZERO INTO WORD IF THERE'S NO CHECKSUM ERROR, ELSE NONZERO. */ + + + if(OP != 0){long ifvar; ifvar=(STATE); switch (ifvar<0? -1 : ifvar>0? 1 : + 0) { case -1: goto L30; case 0: goto L10; case 1: goto L30; }} + if(STATE == 0)return; + if(N == 250)SAVEIO(1,STATE > 0,BUF); + N=MOD(N,250)+1; + H1=MOD(HASH*1093L+221573L,1048576L); + HASH=MOD(H1*1093L+221573L,1048576L); + H1=MOD(H1,1234)*765432+MOD(HASH,123); + N--; + if(STATE > 0)WORD=BUF[N]+H1; + BUF[N]=WORD-H1; + N++; + CKSUM=MOD(CKSUM*13+WORD,1000000000L); + return; + +L10: STATE=OP; + SAVEIO(0,STATE > 0,BUF); + N=1; + if(STATE > 0) goto L15; + HASH=MOD(WORD,1048576L); + BUF[0]=1234L*5678L-HASH; +L13: CKSUM=BUF[0]; + return; + +L15: SAVEIO(1,TRUE,BUF); + HASH=MOD(1234L*5678L-BUF[0],1048576L); + goto L13; + +L30: if(N == 250)SAVEIO(1,STATE > 0,BUF); + N=MOD(N,250)+1; + if(STATE > 0) goto L32; + N--; BUF[N]=CKSUM; N++; + SAVEIO(1,FALSE,BUF); +L32: N--; WORD=BUF[N]-CKSUM; N++; + SAVEIO(-1,STATE > 0,BUF); + STATE=0; + return; +} + + + + + +/* DATA STRUC. ROUTINES (VOCAB, DSTROY, JUGGLE, MOVE, PUT, CARRY, DROP, ATDWRF) + */ + +#undef WORD +#define SAVWRD(OP,WORD) fSAVWRD(OP,&WORD) +#undef VOCAB +long fVOCAB(ID,INIT)long ID, INIT; { +long HASH, I, VOCAB; + +/* LOOK UP ID IN THE VOCABULARY (ATAB) AND RETURN ITS "DEFINITION" (KTAB), OR + * -1 IF NOT FOUND. IF INIT IS POSITIVE, THIS IS AN INITIALISATION CALL SETTING + * UP A KEYWORD VARIABLE, AND NOT FINDING IT CONSTITUTES A BUG. IT ALSO MEANS + * THAT ONLY KTAB VALUES WHICH TAKEN OVER 1000 EQUAL INIT MAY BE CONSIDERED. + * (THUS "STEPS", WHICH IS A MOTION VERB AS WELL AS AN OBJECT, MAY BE LOCATED + * AS AN OBJECT.) AND IT ALSO MEANS THE KTAB VALUE IS TAKEN MOD 1000. */ + + HASH=10000; + /* 1 */ for (I=1; I<=TABSIZ; I++) { + if(KTAB[I] == -1) goto L2; + HASH=HASH+7; + if(INIT >= 0 && KTAB[I]/1000 != INIT) goto L1; + if(ATAB[I] == ID+HASH*HASH) goto L3; +L1: /*etc*/ ; + } /* end loop */ + BUG(21); + +L2: VOCAB= -1; + if(INIT < 0)return(VOCAB); + BUG(5); + +L3: VOCAB=KTAB[I]; + if(INIT >= 0)VOCAB=MOD(VOCAB,1000); + return(VOCAB); +} + + + +#define VOCAB(ID,INIT) fVOCAB(ID,INIT) +#undef DSTROY +void fDSTROY(OBJECT)long OBJECT; { +; + +/* PERMANENTLY ELIMINATE "OBJECT" BY MOVING TO A NON-EXISTENT LOCATION. */ + + + MOVE(OBJECT,0); + return; +} + + + +#define DSTROY(OBJECT) fDSTROY(OBJECT) +#undef JUGGLE +void fJUGGLE(OBJECT)long OBJECT; { +long I, J; + +/* JUGGLE AN OBJECT BY PICKING IT UP AND PUTTING IT DOWN AGAIN, THE PURPOSE + * BEING TO GET THE OBJECT TO THE FRONT OF THE CHAIN OF THINGS AT ITS LOC. */ + + + I=PLACE[OBJECT]; + J=FIXED[OBJECT]; + MOVE(OBJECT,I); + MOVE(OBJECT+100,J); + return; +} + + + +#define JUGGLE(OBJECT) fJUGGLE(OBJECT) +#undef MOVE +void fMOVE(OBJECT,WHERE)long OBJECT, WHERE; { +long FROM; + +/* PLACE ANY OBJECT ANYWHERE BY PICKING IT UP AND DROPPING IT. MAY ALREADY BE + * TOTING, IN WHICH CASE THE CARRY IS A NO-OP. MUSTN'T PICK UP OBJECTS WHICH + * ARE NOT AT ANY LOC, SINCE CARRY WANTS TO REMOVE OBJECTS FROM ATLOC CHAINS. */ + + + if(OBJECT > 100) goto L1; + FROM=PLACE[OBJECT]; + goto L2; +L1: {long x = OBJECT-100; FROM=FIXED[x];} +L2: if(FROM > 0 && FROM <= 300)CARRY(OBJECT,FROM); + DROP(OBJECT,WHERE); + return; +} + + + +#define MOVE(OBJECT,WHERE) fMOVE(OBJECT,WHERE) +#undef PUT +long fPUT(OBJECT,WHERE,PVAL)long OBJECT, PVAL, WHERE; { +long PUT; + +/* PUT IS THE SAME AS MOVE, EXCEPT IT RETURNS A VALUE USED TO SET UP THE + * NEGATED PROP VALUES FOR THE REPOSITORY OBJECTS. */ + + + MOVE(OBJECT,WHERE); + PUT=(-1)-PVAL; + return(PUT); +} + + + +#define PUT(OBJECT,WHERE,PVAL) fPUT(OBJECT,WHERE,PVAL) +#undef CARRY +void fCARRY(OBJECT,WHERE)long OBJECT, WHERE; { +long TEMP; + +/* START TOTING AN OBJECT, REMOVING IT FROM THE LIST OF THINGS AT ITS FORMER + * LOCATION. INCR HOLDNG UNLESS IT WAS ALREADY BEING TOTED. IF OBJECT>100 + * (MOVING "FIXED" SECOND LOC), DON'T CHANGE PLACE OR HOLDNG. */ + + + if(OBJECT > 100) goto L5; + if(PLACE[OBJECT] == -1)return; + PLACE[OBJECT]= -1; + HOLDNG=HOLDNG+1; +L5: if(ATLOC[WHERE] != OBJECT) goto L6; + ATLOC[WHERE]=LINK[OBJECT]; + return; +L6: TEMP=ATLOC[WHERE]; +L7: if(LINK[TEMP] == OBJECT) goto L8; + TEMP=LINK[TEMP]; + goto L7; +L8: LINK[TEMP]=LINK[OBJECT]; + return; +} + + + +#define CARRY(OBJECT,WHERE) fCARRY(OBJECT,WHERE) +#undef DROP +void fDROP(OBJECT,WHERE)long OBJECT, WHERE; { +; + +/* PLACE AN OBJECT AT A GIVEN LOC, PREFIXING IT ONTO THE ATLOC LIST. DECR + * HOLDNG IF THE OBJECT WAS BEING TOTED. */ + + + if(OBJECT > 100) goto L1; + if(PLACE[OBJECT] == -1)HOLDNG=HOLDNG-1; + PLACE[OBJECT]=WHERE; + goto L2; +L1: {long x = OBJECT-100; FIXED[x]=WHERE;} +L2: if(WHERE <= 0)return; + LINK[OBJECT]=ATLOC[WHERE]; + ATLOC[WHERE]=OBJECT; + return; +} + + + +#define DROP(OBJECT,WHERE) fDROP(OBJECT,WHERE) +#undef ATDWRF +long fATDWRF(WHERE)long WHERE; { +long ATDWRF, I; + +/* RETURN THE INDEX OF FIRST DWARF AT THE GIVEN LOCATION, ZERO IF NO DWARF IS + * THERE (OR IF DWARVES NOT ACTIVE YET), -1 IF ALL DWARVES ARE DEAD. IGNORE + * THE PIRATE (6TH DWARF). */ + + + ATDWRF=0; + if(DFLAG < 2)return(ATDWRF); + ATDWRF= -1; + /* 1 */ for (I=1; I<=5; I++) { + if(DLOC[I] == WHERE) goto L2; +L1: if(DLOC[I] != 0)ATDWRF=0; + } /* end loop */ + return(ATDWRF); + +L2: ATDWRF=I; + return(ATDWRF); +} + + + + +#define ATDWRF(WHERE) fATDWRF(WHERE) + + + +/* UTILITY ROUTINES (SETBIT, TSTBIT, RAN, RNDVOC, BUG) */ + +#undef SETBIT +long fSETBIT(BIT)long BIT; { +long I, SETBIT; + +/* RETURNS 2**BIT FOR USE IN CONSTRUCTING BIT-MASKS. */ + + + SETBIT=1; + if(BIT <= 0)return(SETBIT); + /* 1 */ for (I=1; I<=BIT; I++) { +L1: SETBIT=SETBIT+SETBIT; + } /* end loop */ + return(SETBIT); +} + + + +#define SETBIT(BIT) fSETBIT(BIT) +#undef TSTBIT +long fTSTBIT(MASK,BIT)long BIT, MASK; { +long TSTBIT; + +/* RETURNS TRUE IF THE SPECIFIED BIT IS SET IN THE MASK. */ + + + TSTBIT=MOD(MASK/SETBIT(BIT),2) != 0; + return(TSTBIT); +} + + + +#define TSTBIT(MASK,BIT) fTSTBIT(MASK,BIT) +#undef RAN +long fRAN(RANGE)long RANGE; { +static long D, R = 0, RAN, T; + +/* SINCE THE RAN FUNCTION IN LIB40 SEEMS TO BE A REAL LOSE, WE'LL USE ONE OF + * OUR OWN. IT'S BEEN RUN THROUGH MANY OF THE TESTS IN KNUTH VOL. 2 AND + * SEEMS TO BE QUITE RELIABLE. RAN RETURNS A VALUE UNIFORMLY SELECTED + * BETWEEN 0 AND RANGE-1. */ + + + D=1; + if(R != 0 && RANGE >= 0) goto L1; + DATIME(D,T); + R=MOD(T+5,1048576L); + D=1000+MOD(D,1000); +L1: /* 2 */ for (T=1; T<=D; T++) { +L2: R=MOD(R*1093L+221587L,1048576L); + } /* end loop */ + RAN=(RANGE*R)/1048576; + return(RAN); +} + + + +#define RAN(RANGE) fRAN(RANGE) +#undef RNDVOC +long fRNDVOC(CHAR,FORCE)long CHAR, FORCE; { +long DIV, I, J, RNDVOC; + +/* SEARCHES THE VOCABULARY FOR A WORD WHOSE SECOND CHARACTER IS CHAR, AND + * CHANGES THAT WORD SUCH THAT EACH OF THE OTHER FOUR CHARACTERS IS A + * RANDOM LETTER. IF FORCE IS NON-ZERO, IT IS USED AS THE NEW WORD. + * RETURNS THE NEW WORD. */ + + + RNDVOC=FORCE; + if(RNDVOC != 0) goto L3; + /* 1 */ for (I=1; I<=5; I++) { + J=11+RAN(26); + if(I == 2)J=CHAR; +L1: RNDVOC=RNDVOC*64+J; + } /* end loop */ +L3: J=10000; + DIV=64L*64L*64L; + /* 5 */ for (I=1; I<=TABSIZ; I++) { + J=J+7; + if(MOD((ATAB[I]-J*J)/DIV,64L) == CHAR) goto L8; +L5: /*etc*/ ; + } /* end loop */ + BUG(5); + +L8: ATAB[I]=RNDVOC+J*J; + return(RNDVOC); +} + + + +#define RNDVOC(CHAR,FORCE) fRNDVOC(CHAR,FORCE) +#undef BUG +void fBUG(NUM)long NUM; { + +/* THE FOLLOWING CONDITIONS ARE CURRENTLY CONSIDERED FATAL BUGS. NUMBERS < 20 + * ARE DETECTED WHILE READING THE DATABASE; THE OTHERS OCCUR AT "RUN TIME". + * 0 MESSAGE LINE > 70 CHARACTERS + * 1 NULL LINE IN MESSAGE + * 2 TOO MANY WORDS OF MESSAGES + * 3 TOO MANY TRAVEL OPTIONS + * 4 TOO MANY VOCABULARY WORDS + * 5 REQUIRED VOCABULARY WORD NOT FOUND + * 6 TOO MANY RTEXT MESSAGES + * 7 TOO MANY HINTS + * 8 LOCATION HAS COND BIT BEING SET TWICE + * 9 INVALID SECTION NUMBER IN DATABASE + * 10 TOO MANY LOCATIONS + * 11 TOO MANY CLASS OR TURN MESSAGES + * 20 SPECIAL TRAVEL (500>L>300) EXCEEDS GOTO LIST + * 21 RAN OFF END OF VOCABULARY TABLE + * 22 VOCABULARY TYPE (N/1000) NOT BETWEEN 0 AND 3 + * 23 INTRANSITIVE ACTION VERB EXCEEDS GOTO LIST + * 24 TRANSITIVE ACTION VERB EXCEEDS GOTO LIST + * 25 CONDITIONAL TRAVEL ENTRY WITH NO ALTERNATIVE + * 26 LOCATION HAS NO TRAVEL ENTRIES + * 27 HINT NUMBER EXCEEDS GOTO LIST + * 28 INVALID MONTH RETURNED BY DATE FUNCTION + * 29 TOO MANY PARAMETERS GIVEN TO SETPRM */ + + printf("Fatal error %d. See source code for interpretation.\n", + NUM); + exit(FALSE); +} + + + + + +/* MACHINE DEPENDENT ROUTINES (MAPLIN, TYPE, MPINIT, SAVEIO) */ + +#define BUG(NUM) fBUG(NUM) +#undef MAPLIN +void fMAPLIN(FIL)long FIL; { +long I, VAL; static FILE *OPENED = NULL; + +/* READ A LINE OF INPUT, EITHER FROM A FILE (IF FIL=.TRUE.) OR FROM THE + * KEYBOARD, TRANSLATE THE CHARS TO INTEGERS IN THE RANGE 0-126 AND STORE + * THEM IN THE COMMON ARRAY "INLINE". INTEGER VALUES ARE AS FOLLOWS: + * 0 = SPACE [ASCII CODE 40 OCTAL, 32 DECIMAL] + * 1-2 = !" [ASCII 41-42 OCTAL, 33-34 DECIMAL] + * 3-10 = '()*+,-. [ASCII 47-56 OCTAL, 39-46 DECIMAL] + * 11-36 = UPPER-CASE LETTERS + * 37-62 = LOWER-CASE LETTERS + * 63 = PERCENT (%) [ASCII 45 OCTAL, 37 DECIMAL] + * 64-73 = DIGITS, 0 THROUGH 9 + * REMAINING CHARACTERS CAN BE TRANSLATED ANY WAY THAT IS CONVENIENT; + * THE "TYPE" ROUTINE BELOW IS USED TO MAP THEM BACK TO CHARACTERS WHEN + * NECESSARY. THE ABOVE MAPPINGS ARE REQUIRED SO THAT CERTAIN SPECIAL + * CHARACTERS ARE KNOWN TO FIT IN 6 BITS AND/OR CAN BE EASILY SPOTTED. + * ARRAY ELEMENTS BEYOND THE END OF THE LINE SHOULD BE FILLED WITH 0, + * AND LNLENG SHOULD BE SET TO THE INDEX OF THE LAST CHARACTER. + * + * IF THE DATA FILE USES A CHARACTER OTHER THAN SPACE (E.G., TAB) TO + * SEPARATE NUMBERS, THAT CHARACTER SHOULD ALSO TRANSLATE TO 0. + * + * THIS PROCEDURE MAY USE THE MAP1,MAP2 ARRAYS TO MAINTAIN STATIC DATA FOR + * THE MAPPING. MAP2(1) IS SET TO 0 WHEN THE PROGRAM STARTS + * AND IS NOT CHANGED THEREAFTER UNLESS THE ROUTINES ON THIS PAGE CHOOSE + * TO DO SO. + * + * NOTE THAT MAPLIN IS EXPECTED TO OPEN THE FILE THE FIRST TIME IT IS + * ASKED TO READ A LINE FROM IT. THAT IS, THERE IS NO OTHER PLACE WHERE + * THE DATA FILE IS OPENED. */ + + + if(MAP2[1] == 0)MPINIT(); + + if(FIL) goto L15; + gets(INLINE+1); + if(feof(stdin)) score(1); + goto L20; + +L15: if(!OPENED){ +#ifdef AMIGA + OPENED=fopen("ram:adventure.text","r" /* NOT binary */); + if(!OPENED) +#endif + OPENED=fopen("adventure.text","r" /* NOT binary */); + if(!OPENED){printf("Can't read adventure.text!\n"); exit(FALSE);} + } + fgets(INLINE+1,100,OPENED); + +L20: LNLENG=0; + /* 25 */ for (I=1; I<=100 && INLINE[I]!=0; I++) { + VAL=INLINE[I]+1; + INLINE[I]=MAP1[VAL]; +L25: if(INLINE[I] != 0)LNLENG=I; + } /* end loop */ + LNPOSN=1; + if(FIL && LNLENG == 0) goto L15; +/* ABOVE IS TO GET AROUND AN F40 COMPILER BUG WHEREIN IT READS A BLANK + * LINE WHENEVER A CRLF IS BROKEN ACROSS A RECORD BOUNDARY. */ + return; +} + + + +#define MAPLIN(FIL) fMAPLIN(FIL) +#undef TYPE +void fTYPE() { +long I, VAL; + +/* TYPE THE FIRST "LNLENG" CHARACTERS STORED IN INLINE, MAPPING THEM + * FROM INTEGERS TO TEXT PER THE RULES DESCRIBED ABOVE. INLINE(I), + * I=1,LNLENG MAY BE CHANGED BY THIS ROUTINE. */ + + + if(LNLENG != 0) goto L10; + printf("\n"); + return; + +L10: if(MAP2[1] == 0)MPINIT(); + /* 20 */ for (I=1; I<=LNLENG; I++) { + VAL=INLINE[I]; +L20: {long x = VAL+1; INLINE[I]=MAP2[x];} + } /* end loop */ + {long x = LNLENG+1; INLINE[x]=0;} + printf("%s\n",INLINE+1); + return; +} + + + +#define TYPE() fTYPE() +#undef MPINIT +void fMPINIT() { +long FIRST, I, J, LAST, VAL; +static long RUNS[7][2] = {32,34, 39,46, 65,90, 97,122, 37,37, 48,57, 0,126}; + + + /* 10 */ for (I=1; I<=128; I++) { +L10: MAP1[I]= -1; + } /* end loop */ + VAL=0; + /* 20 */ for (I=0; I<7; I++) { + FIRST=RUNS[I][0]; + LAST=RUNS[I][1]; + /* 22 */ for (J=FIRST; J<=LAST; J++) { + J++; if(MAP1[J] >= 0) goto L22; + MAP1[J]=VAL; + VAL=VAL+1; +L22: J--; + } /* end loop */ +L20: /*etc*/ ; + } /* end loop */ + MAP1[128]=MAP1[10]; +/* FOR THIS VERSION, TAB (9) MAPS TO SPACE (32), SO DEL (127) USES TAB'S VALUE */ + MAP1[10]=MAP1[33]; + MAP1[11]=MAP1[33]; + + /* 30 */ for (I=0; I<=126; I++) { + I++; VAL=MAP1[I]+1; I--; + MAP2[VAL]=I*('B'-'A'); +L30: if(I >= 64)MAP2[VAL]=(I-64)*('B'-'A')+'@'; + } /* end loop */ + + return; +} + + + +#define MPINIT() fMPINIT() +#undef SAVEIO +void fSAVEIO(OP,IN,ARR)long ARR[], IN, OP; { +static FILE *F; char NAME[50]; + +/* IF OP=0, ASK FOR A FILE NAME AND OPEN A FILE. (IF IN=.TRUE., THE FILE IS FOR + * INPUT, ELSE OUTPUT.) IF OP>0, READ/WRITE ARR FROM/INTO THE PREVIOUSLY-OPENED + * FILE. (ARR IS A 250-INTEGER ARRAY.) IF OP<0, FINISH READING/WRITING THE + * FILE. (FINISHING WRITING CAN BE A NO-OP IF A "STOP" STATEMENT DOES IT + * AUTOMATICALLY. FINISHING READING CAN BE A NO-OP AS LONG AS A SUBSEQUENT + * SAVEIO(0,.FALSE.,X) WILL STILL WORK.) IF YOU CAN CATCH ERRORS (E.G., NO SUCH + * FILE) AND TRY AGAIN, GREAT. DEC F40 CAN'T. */ + + + {long ifvar; ifvar=(OP); switch (ifvar<0? -1 : ifvar>0? 1 : 0) { case -1: + goto L10; case 0: goto L20; case 1: goto L30; }} + +L10: fclose(F); + return; + +L20: printf("\nFile name: "); + gets(NAME); + F=fopen(NAME,(IN ? READ_MODE : WRITE_MODE)); + if(F == NULL) {printf("Can't open file, try again.\n"); goto L20;} + return; + +L30: if(IN)fread(ARR,4,250,F); + if(!IN)fwrite(ARR,4,250,F); + return; + +} + + + +long fIABS(N)long N; {return(N<0? -N : N);} +long fMOD(N,M)long N, M; {return(N%M);} diff --git a/misc.h b/misc.h new file mode 100644 index 0000000..6654ea9 --- /dev/null +++ b/misc.h @@ -0,0 +1,78 @@ +#ifdef __MSDOS__ /* define fopen modes for binary files */ +#define READ_MODE "rb" +#define WRITE_MODE "wb" +#else +#define READ_MODE "r" +#define WRITE_MODE "w" +#endif + +extern void fSPEAK(long); +#define SPEAK(N) fSPEAK(N) +extern void fPSPEAK(long,long); +#define PSPEAK(MSG,SKIP) fPSPEAK(MSG,SKIP) +extern void fRSPEAK(long); +#define RSPEAK(I) fRSPEAK(I) +extern void fSETPRM(long,long,long); +#define SETPRM(FIRST,P1,P2) fSETPRM(FIRST,P1,P2) +extern void fGETIN(long*,long*,long*,long*); +#define GETIN(WORD1,WORD1X,WORD2,WORD2X) fGETIN(&WORD1,&WORD1X,&WORD2,&WORD2X) +extern long fYES(long,long,long); +#define YES(X,Y,Z) fYES(X,Y,Z) +extern long fGETNUM(long); +#define GETNUM(K) fGETNUM(K) +extern long fGETTXT(long,long,long,long); +#define GETTXT(SKIP,ONEWRD,UPPER,HASH) fGETTXT(SKIP,ONEWRD,UPPER,HASH) +extern long fMAKEWD(long); +#define MAKEWD(LETTRS) fMAKEWD(LETTRS) +extern void fPUTTXT(long,long*,long,long); +#define PUTTXT(WORD,STATE,CASE,HASH) fPUTTXT(WORD,&STATE,CASE,HASH) +extern void fSHFTXT(long,long); +#define SHFTXT(FROM,DELTA) fSHFTXT(FROM,DELTA) +extern void fTYPE0(); +#define TYPE0() fTYPE0() +extern void fSAVWDS(long*,long*,long*,long*,long*,long*,long*); +#define SAVWDS(W1,W2,W3,W4,W5,W6,W7) fSAVWDS(&W1,&W2,&W3,&W4,&W5,&W6,&W7) +extern void fSAVARR(long*,long); +#define SAVARR(ARR,N) fSAVARR(ARR,N) +extern void fSAVWRD(long,long*); +#define SAVWRD(OP,WORD) fSAVWRD(OP,&WORD) +extern long fVOCAB(long,long); +#define VOCAB(ID,INIT) fVOCAB(ID,INIT) +extern void fDSTROY(long); +#define DSTROY(OBJECT) fDSTROY(OBJECT) +extern void fJUGGLE(long); +#define JUGGLE(OBJECT) fJUGGLE(OBJECT) +extern void fMOVE(long,long); +#define MOVE(OBJECT,WHERE) fMOVE(OBJECT,WHERE) +extern long fPUT(long,long,long); +#define PUT(OBJECT,WHERE,PVAL) fPUT(OBJECT,WHERE,PVAL) +extern void fCARRY(long,long); +#define CARRY(OBJECT,WHERE) fCARRY(OBJECT,WHERE) +extern void fDROP(long,long); +#define DROP(OBJECT,WHERE) fDROP(OBJECT,WHERE) +extern long fATDWRF(long); +#define ATDWRF(WHERE) fATDWRF(WHERE) +extern long fSETBIT(long); +#define SETBIT(BIT) fSETBIT(BIT) +extern long fTSTBIT(long,long); +#define TSTBIT(MASK,BIT) fTSTBIT(MASK,BIT) +extern long fRAN(long); +#define RAN(RANGE) fRAN(RANGE) +extern long fRNDVOC(long,long); +#define RNDVOC(CHAR,FORCE) fRNDVOC(CHAR,FORCE) +extern void fBUG(long); +#define BUG(NUM) fBUG(NUM) +extern void fMAPLIN(long); +#define MAPLIN(FIL) fMAPLIN(FIL) +extern void fTYPE(); +#define TYPE() fTYPE() +extern void fMPINIT(); +#define MPINIT() fMPINIT() +extern void fSAVEIO(long,long,long*); +#define SAVEIO(OP,IN,ARR) fSAVEIO(OP,IN,ARR) +extern void fDATIME(long*,long*); +#define DATIME(D,T) fDATIME(&D,&T) +extern long fIABS(long); +#define IABS(N) fIABS(N) +extern long fMOD(long,long); +#define MOD(N,M) fMOD(N,M) diff --git a/score.c b/score.c new file mode 100644 index 0000000..acda23f --- /dev/null +++ b/score.c @@ -0,0 +1,119 @@ +#include "misc.h" +#include "main.h" +#include "share.h" + +#define TRUE (0==0) +#define FALSE (0!=0) + +/* + * SCORING AND WRAP-UP + */ + +void score(MODE)long MODE; { + /* <0 if scoring, >0 if quitting, =0 if died or won */ + +/* THE PRESENT SCORING ALGORITHM IS AS FOLLOWS: + * OBJECTIVE: POINTS: PRESENT TOTAL POSSIBLE: + * GETTING WELL INTO CAVE 25 25 + * EACH TREASURE < CHEST 12 60 + * TREASURE CHEST ITSELF 14 14 + * EACH TREASURE > CHEST 16 224 + * SURVIVING (MAX-NUM)*10 30 + * NOT QUITTING 4 4 + * REACHING "CLOSNG" 25 25 + * "CLOSED": QUIT/KILLED 10 + * KLUTZED 25 + * WRONG WAY 30 + * SUCCESS 45 45 + * CAME TO WITT'S END 1 1 + * ROUND OUT THE TOTAL 2 2 + * TOTAL: 430 + * POINTS CAN ALSO BE DEDUCTED FOR USING HINTS OR TOO MANY TURNS, OR FOR + * SAVING INTERMEDIATE POSITIONS. */ + +L20000: SCORE=0; + MXSCOR=0; + +/* FIRST TALLY UP THE TREASURES. MUST BE IN BUILDING AND NOT BROKEN. + * GIVE THE POOR GUY 2 POINTS JUST FOR FINDING EACH TREASURE. */ + + /* 20010 */ for (I=50; I<=MAXTRS; I++) { + if(PTEXT[I] == 0) goto L20010; + K=12; + if(I == CHEST)K=14; + if(I > CHEST)K=16; + if(PROP[I] >= 0)SCORE=SCORE+2; + if(PLACE[I] == 3 && PROP[I] == 0)SCORE=SCORE+K-2; + MXSCOR=MXSCOR+K; +L20010: /*etc*/ ; + } /* end loop */ + +/* NOW LOOK AT HOW HE FINISHED AND HOW FAR HE GOT. MAXDIE AND NUMDIE TELL US + * HOW WELL HE SURVIVED. DFLAG WILL + * TELL US IF HE EVER GOT SUITABLY DEEP INTO THE CAVE. CLOSNG STILL INDICATES + * WHETHER HE REACHED THE ENDGAME. AND IF HE GOT AS FAR AS "CAVE CLOSED" + * (INDICATED BY "CLOSED"), THEN BONUS IS ZERO FOR MUNDANE EXITS OR 133, 134, + * 135 IF HE BLEW IT (SO TO SPEAK). */ + + SCORE=SCORE+(MAXDIE-NUMDIE)*10; + MXSCOR=MXSCOR+MAXDIE*10; + if(MODE == 0)SCORE=SCORE+4; + MXSCOR=MXSCOR+4; + if(DFLAG != 0)SCORE=SCORE+25; + MXSCOR=MXSCOR+25; + if(CLOSNG)SCORE=SCORE+25; + MXSCOR=MXSCOR+25; + if(!CLOSED) goto L20020; + if(BONUS == 0)SCORE=SCORE+10; + if(BONUS == 135)SCORE=SCORE+25; + if(BONUS == 134)SCORE=SCORE+30; + if(BONUS == 133)SCORE=SCORE+45; +L20020: MXSCOR=MXSCOR+45; + +/* DID HE COME TO WITT'S END AS HE SHOULD? */ + + if(PLACE[MAGZIN] == 108)SCORE=SCORE+1; + MXSCOR=MXSCOR+1; + +/* ROUND IT OFF. */ + + SCORE=SCORE+2; + MXSCOR=MXSCOR+2; + +/* DEDUCT FOR HINTS/TURNS/SAVES. HINTS < 4 ARE SPECIAL; SEE DATABASE DESC. */ + + /* 20030 */ for (I=1; I<=HNTMAX; I++) { +L20030: if(HINTED[I])SCORE=SCORE-HINTS[I][2]; + } /* end loop */ + if(NOVICE)SCORE=SCORE-5; + if(CLSHNT)SCORE=SCORE-10; + SCORE=SCORE-TRNLUZ-SAVED; + +/* RETURN TO SCORE COMMAND IF THAT'S WHERE WE CAME FROM. */ + + if(MODE < 0) return; + +/* THAT SHOULD BE GOOD ENOUGH. LET'S TELL HIM ALL ABOUT IT. */ + + if(SCORE+TRNLUZ+1 >= MXSCOR && TRNLUZ != 0)RSPEAK(242); + if(SCORE+SAVED+1 >= MXSCOR && SAVED != 0)RSPEAK(143); + SETPRM(1,SCORE,MXSCOR); + SETPRM(3,TURNS,TURNS); + RSPEAK(262); + /* 20200 */ for (I=1; I<=CLSSES; I++) { + if(CVAL[I] >= SCORE) goto L20210; +L20200: /*etc*/ ; + } /* end loop */ + SPK=265; + goto L25000; + +L20210: SPEAK(CTEXT[I]); + SPK=264; + if(I >= CLSSES) goto L25000; + I=CVAL[I]+1-SCORE; + SETPRM(1,I,I); + SPK=263; +L25000: RSPEAK(SPK); + exit(FALSE); + +} diff --git a/share.h b/share.h new file mode 100644 index 0000000..ff4252b --- /dev/null +++ b/share.h @@ -0,0 +1,24 @@ +extern void score(long); +extern long ABBNUM, ACTSPK[], AMBER, ATTACK, AXE, BACK, BATTER, BEAR, + BIRD, BLOOD, BONUS, + BOTTLE, CAGE, CAVE, CAVITY, CHAIN, CHASM, CHEST, CHLOC, CHLOC2, + CLAM, CLOCK1, CLOCK2, CLOSED, CLOSNG, CLSHNT, CLSMAX, CLSSES, + COINS, COND[], CONDS, CTEXT[], CVAL[], DALTLC, DETAIL, + DKILL, DOOR, DPRSSN, DRAGON, DSEEN[], DTOTAL, DWARF, EGGS, + EMRALD, ENTER, ENTRNC, FIND, FISSUR, FIXD[], FOOBAR, FOOD, + GRATE, HINT, HINTED[], HINTLC[], HINTS[][5], HNTMAX, + HNTSIZ, I, INVENT, IGO, IWEST, J, JADE, K, K2, KEY[], KEYS, KK, + KNFLOC, KNIFE, KQ, L, LAMP, LIMIT, LINSIZ, LINUSE, LL, + LMWARN, LOC, LOCK, LOCSIZ, LOCSND[], LOOK, LTEXT[], + MAGZIN, MAXDIE, MAXTRS, MESH, MESSAG, MIRROR, MXSCOR, + NEWLOC, NOVICE, NUGGET, NUL, NUMDIE, OBJ, OBJSND[], + OBJTXT[], ODLOC[], OGRE, OIL, OLDLC2, OLDLOC, OLDOBJ, OYSTER, + PANIC, PEARL, PILLOW, PLAC[], PLANT, PLANT2, PROP[], PYRAM, + RESER, ROD, ROD2, RTXSIZ, RUBY, RUG, SAPPH, SAVED, SAY, + SCORE, SECT, SETUP, SIGN, SNAKE, SPK, STEPS, STEXT[], STICK, + STREAM, TABNDX, TALLY, THRESH, THROW, TK[], TRAVEL[], TRIDNT, + TRNDEX, TRNLUZ, TRNSIZ, TRNVAL[], TRNVLS, TROLL, TROLL2, TRVS, + TRVSIZ, TTEXT[], TURNS, URN, V1, V2, VASE, VEND, VERB, + VOLCAN, VRBSIZ, VRSION, WATER, WD1, WD1X, WD2, WD2X, + WZDARK, ZZWORD; + -- 2.31.1