From: Eric S. Raymond Date: Thu, 16 Feb 2017 16:59:50 +0000 (-0500) Subject: Don Wood's 430-point Adventure 2.5 from 1995, from rec.games.int-fiction. X-Git-Tag: seed~114 X-Git-Url: https://jxself.org/git/?p=open-adventure.git;a=commitdiff_plain;h=24d7aeaf8a1dc13034884044139728045604fc37 Don Wood's 430-point Adventure 2.5 from 1995, from rec.games.int-fiction. --- 24d7aeaf8a1dc13034884044139728045604fc37 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; +