From 18767d52dd053cf6c851ded2597697674ca255c1 Mon Sep 17 00:00:00 2001 From: "Eric S. Raymond" Date: Sun, 21 May 2017 13:12:24 -0400 Subject: [PATCH] Fix up case on all comments to make them more readable. No code changes. The all-capsing was a FORTRAN remnant.Also, we change a few FORTRANisms so they are less confusing in this C context; ".TRUE." and ".FALSE." become "true" and "false", "MOD" is mapped to % in places tha t are like C expressions and (usually) "modulo" in places that aren't. --- actions1.c | 116 +++++++------- actions2.c | 42 ++--- funcs.h | 34 ++-- init.c | 464 ++++++++++++++++++++++++++--------------------------- main.c | 334 +++++++++++++++++++------------------- misc.c | 336 +++++++++++++++++++------------------- score.c | 62 +++---- 7 files changed, 694 insertions(+), 694 deletions(-) diff --git a/actions1.c b/actions1.c index 2c7d336..55413be 100644 --- a/actions1.c +++ b/actions1.c @@ -11,8 +11,8 @@ * 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. */ +/* Analyse a verb. remember what it was, go back for object if second word + * unless verb is "say", which snarfs arbitrary second word. */ int action(long STARTAT) { switch(STARTAT) { @@ -28,7 +28,7 @@ L4000: VERB=K; if(VERB == SAY)OBJ=WD2; if(OBJ > 0) goto L4090; -/* ANALYSE AN INTRANSITIVE VERB (IE, NO OBJECT GIVEN YET). */ +/* 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; @@ -48,7 +48,7 @@ L4080: switch (VERB-1) { case 0: goto L8010; case 1: return(8000); case 2: * RESU FLY LSTN ZZZZ */ BUG(23); -/* ANALYSE A TRANSITIVE VERB. */ +/* 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; @@ -68,11 +68,11 @@ L4090: switch (VERB-1) { case 0: goto L9010; case 1: goto L9020; case 2: goto * 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. */ +/* 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; @@ -109,23 +109,23 @@ L5190: if((VERB == FIND || VERB == INVENT) && WD2 <= 0) goto L5010; -/* ROUTINES FOR PERFORMING THE VARIOUS ACTION VERBS */ +/* 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. */ +/* 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. */ +/* 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. */ +/* 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. */ +/* 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); @@ -139,7 +139,7 @@ L9035: WD2=0; OBJ=0; return(2630); -/* LOCK, UNLOCK, NO OBJECT GIVEN. ASSUME VARIOUS THINGS IF PRESENT. */ +/* Lock, unlock, no object given. Assume various things if present. */ L8040: SPK=28; if(HERE(CLAM))OBJ=CLAM; @@ -150,7 +150,7 @@ L8040: SPK=28; if(HERE(CHAIN))OBJ=CHAIN; if(OBJ == 0) return(2011); -/* LOCK, UNLOCK OBJECT. SPECIAL STUFF FOR OPENING CLAM/OYSTER AND FOR CHAIN. */ +/* 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; @@ -172,7 +172,7 @@ L9043: K=34+PROP[GRATE]; K=K+2*PROP[GRATE]; return(2010); -/* CLAM/OYSTER. */ +/* Clam/Oyster. */ L9046: K=0; if(OBJ == OYSTER)K=1; SPK=124+K; @@ -185,7 +185,7 @@ L9046: K=0; DROP(PEARL,105); return(2011); -/* CHAIN. */ +/* Chain. */ L9048: if(VERB == LOCK) goto L9049; SPK=171; if(PROP[BEAR] == 0)SPK=41; @@ -206,7 +206,7 @@ L9049: SPK=172; FIXED[CHAIN]= -1; return(2011); -/* LIGHT. APPLICABLE ONLY TO LAMP AND URN. */ +/* 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; @@ -227,7 +227,7 @@ L9073: SPK=38; PROP[URN]=2; return(2011); -/* EXTINGUISH. LAMP, URN, DRAGON/VOLCANO (NICE TRY). */ +/* 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; @@ -247,7 +247,7 @@ L9086: PROP[LAMP]=0; if(DARK(0))RSPEAK(16); return(2012); -/* WAVE. NO EFFECT UNLESS WAVING ROD AT FISSURE OR AT BIRD. */ +/* 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)))) @@ -267,12 +267,12 @@ L9094: DROP(JADE,LOC); SPK=208; return(2011); -/* ATTACK ALSO MOVED INTO SEPARATE MODULE. */ +/* 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. */ +/* 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); @@ -302,8 +302,8 @@ L9132: PROP[DOOR]=0; L9134: OBJ=URN; goto L9220; -/* EAT. INTRANSITIVE: ASSUME FOOD IF PRESENT, ELSE ASK WHAT. TRANSITIVE: FOOD - * OK, SOME THINGS LOSE APPETITE, REST ARE RIDICULOUS. */ +/* 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); @@ -316,8 +316,8 @@ L9140: if(OBJ == FOOD) goto L8142; 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. */ +/* 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); @@ -335,7 +335,7 @@ L9153: DSTROY(BLOOD); SPK=240; return(2011); -/* RUB. YIELDS VARIOUS SNIDE REMARKS EXCEPT FOR LIT URN. */ +/* Rub. Yields various snide remarks except for lit urn. */ L9160: if(OBJ != LAMP)SPK=76; if(OBJ != URN || PROP[URN] != 2) return(2011); @@ -347,16 +347,16 @@ L9160: if(OBJ != LAMP)SPK=76; SPK=216; return(2011); -/* THROW MOVED INTO SEPARATE MODULE. */ +/* Throw moved into separate module. */ L9170: return(throw()); -/* QUIT. INTRANSITIVE ONLY. VERIFY INTENT AND EXIT IF THAT'S WHAT HE WANTS. */ +/* 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. */ +/* 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; @@ -364,7 +364,7 @@ L9190: if(AT(OBJ) || (LIQ(0) == OBJ && AT(BOTTLE)) || K == LIQLOC(LOC) || (OBJ = if(TOTING(OBJ))SPK=24; return(2011); -/* INVENTORY. IF OBJECT, TREAT SAME AS FIND. ELSE REPORT ON CURRENT BURDEN. */ +/* Inventory. If object, treat same as find. Else report on current burden. */ L8200: SPK=98; /* 8201 */ for (I=1; I<=100; I++) { @@ -379,12 +379,12 @@ L8201: /*etc*/ ; if(TOTING(BEAR))SPK=141; return(2011); -/* FEED/FILL ARE IN THE OTHER MODULE. */ +/* 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! */ +/* Blast. No effect unless you've got dynamite, which is a neat trick! */ L9230: if(PROP[ROD2] < 0 || !CLOSED) return(2011); BONUS=133; @@ -393,7 +393,7 @@ L9230: if(PROP[ROD2] < 0 || !CLOSED) return(2011); RSPEAK(BONUS); score(0); -/* SCORE. CALL SCORING ROUTINE BUT TELL IT TO RETURN. */ +/* Score. Call scoring routine but tell it to return. */ L8240: score(-1); SETPRM(1,SCORE,MXSCOR); @@ -416,7 +416,7 @@ L8252: FOOBAR=K; 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. */ +/* 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; @@ -426,14 +426,14 @@ L8252: FOOBAR=K; PSPEAK(EGGS,K); return(2012); -/* BRIEF. INTRANSITIVE ONLY. SUPPRESS LONG DESCRIPTIONS AFTER FIRST TIME. */ +/* 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. */ +/* 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; @@ -449,7 +449,7 @@ L9270: if(DARK(0)) goto L5190; L9275: CLSHNT=YES(192,193,54); return(2012); -/* BREAK. ONLY WORKS FOR MIRROR IN REPOSITORY AND, OF COURSE, THE VASE. */ +/* 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; @@ -463,15 +463,15 @@ L9282: SPK=198; FIXED[VASE]= -1; return(2011); -/* WAKE. ONLY USE IS TO DISTURB THE DWARVES. */ +/* 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). */ +/* 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); @@ -479,8 +479,8 @@ L8300: SPK=201; 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). */ +/* 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; @@ -488,12 +488,12 @@ L8305: DATIME(I,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. */ +/* 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); @@ -520,7 +520,7 @@ L8305: DATIME(I,K); RSPEAK(266); exit(0); -/* RESUME. READ A SUSPENDED GAME BACK FROM A FILE. */ +/* Resume. Read a suspended game back from a file. */ L8310: KK=1; if(LOC == 1 && ABB[1] == 1) goto L8305; @@ -536,7 +536,7 @@ L8312: SETPRM(1,K/10,MOD(K,10)); L8318: RSPEAK(270); exit(0); -/* FLY. SNIDE REMARKS UNLESS HOVERING RUG IS HERE. */ +/* Fly. Snide remarks unless hovering rug is here. */ L8320: if(PROP[RUG] != 2)SPK=224; if(!HERE(RUG))SPK=225; @@ -554,7 +554,7 @@ L9320: if(OBJ != RUG) return(2011); RSPEAK(SPK); return(2); -/* LISTEN. INTRANSITIVE ONLY. PRINT STUFF BASED ON OBJSND/LOCSND. */ +/* Listen. Intransitive only. Print stuff based on objsnd/locsnd. */ L8330: SPK=228; K=LOCSND[LOC]; @@ -572,7 +572,7 @@ L8335: /*etc*/ ; } /* end loop */ return(2011); -/* Z'ZZZ (WORD GETS RECOMPUTED AT STARTUP; DIFFERENT EACH GAME). */ +/* 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); diff --git a/actions2.c b/actions2.c index 75179dc..ae2c2f4 100644 --- a/actions2.c +++ b/actions2.c @@ -3,9 +3,9 @@ #include "share.h" #include "funcs.h" -/* 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 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. */ int carry(void) { if(TOTING(OBJ)) return(2011); @@ -53,9 +53,9 @@ L9015: SPK=238; 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 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. */ int discard(bool just_do_it) { if(just_do_it) goto L9021; @@ -127,9 +127,9 @@ L9028: PROP[VASE]=2; 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. 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. */ int attack() { I=ATDWRF(LOC); @@ -170,9 +170,9 @@ L9126: if(OBJ == 0)SPK=44; 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. */ +/* 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; @@ -210,9 +210,9 @@ L9129: /*etc*/ ; 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. 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. */ int throw() { if(TOTING(ROD2) && OBJ == ROD && !TOTING(ROD))OBJ=ROD2; @@ -244,7 +244,7 @@ L9175: RSPEAK(SPK); K=NUL; return(8); -/* THIS'LL TEACH HIM TO THROW THE AXE AT THE BEAR! */ +/* This'll teach him to throw the axe at the bear! */ L9176: SPK=164; DROP(AXE,LOC); FIXED[AXE]= -1; @@ -252,12 +252,12 @@ L9176: SPK=164; JUGGLE(BEAR); return(2011); -/* BUT THROWING FOOD IS ANOTHER STORY. */ +/* But throwing food is another story. */ L9177: OBJ=BEAR; return(feed()); L9178: SPK=159; -/* SNARF A TREASURE FOR THE TROLL. */ +/* Snarf a treasure for the troll. */ DROP(OBJ,0); MOVE(TROLL,0); MOVE(TROLL+100,0); @@ -267,8 +267,8 @@ L9178: SPK=159; return(2011); } -/* FEED. IF BIRD, NO SEED. SNAKE, DRAGON, TROLL: QUIP. IF DWARF, MAKE HIM - * MAD. BEAR, SPECIAL. */ +/* Feed. If bird, no seed. snake, dragon, troll: quip. If dwarf, make him + * mad. Bear, special. */ int feed() { if(OBJ != BIRD) goto L9212; @@ -310,7 +310,7 @@ L9216: SPK=14; return(2011); } -/* FILL. BOTTLE OR URN MUST BE EMPTY, AND LIQUID AVAILABLE. (VASE IS NASTY.) */ +/* Fill. Bottle or urn must be empty, and liquid available. (Vase is nasty.) */ int fill() { if(OBJ == VASE) goto L9222; diff --git a/funcs.h b/funcs.h index 3f737c5..e86fb2c 100644 --- a/funcs.h +++ b/funcs.h @@ -1,18 +1,18 @@ #include -/* STATEMENT FUNCTIONS +/* 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 */ + * 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) @@ -28,11 +28,11 @@ #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. */ +/* 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 index 0694b1b..22622b7 100644 --- a/init.c +++ b/init.c @@ -6,161 +6,161 @@ #include /* - * INITIALISATION + * 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, +/* 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 + * 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". + * 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 0500 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 + * This says that, from 11, 49 takes him to 8 unless PROP(3)=0, in which + * case he goes to 9. Verb 50 takes him to 9 regardless of PROP(3). + * Section 4: Vocabulary. Each line contains a number (n), a tab, and a + * five-letter word. Call M=N/1000. If M=0, then the word is a motion + * verb for use in travelling (see section 3). Else, if M=1, the word is + * an object. Else, if M=2, the word is an action verb (such as "carry" + * or "attack"). Else, if M=3, the word is a special case verb (such as + * "dig") and N % 1000 is an index into section 6. Objects from 50 to + * (currently, anyway) 79 are considered treasures (for pirate, closeout). + * Section 5: Object descriptions. Each line contains a number (N), a tab, + * and a message. If N is from 1 to 100, the message is the "inventory" + * message for object n. Otherwise, N should be 000, 100, 200, etc., and + * the message should be the description of the preceding object when its + * prop value is N/100. The N/100 is used only to distinguish multiple + * messages from multi-line messages; the prop info actually requires all + * messages for an object to be present and consecutive. Properties which + * produce no message should be given the message ">$<". + * 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 % 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 */ + * %9 = A 9-digit number + * %B = Variable number of blanks + * %! = The entire message should be suppressed */ static bool quick_init(void); static int raw_init(void); @@ -178,15 +178,15 @@ void initialise(void) { static int raw_init(void) { 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). */ +/* 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; @@ -208,7 +208,7 @@ L1001: /*etc*/ ; CLSSES=0; TRNVLS=0; -/* START NEW DATA SECTION. SECT IS THE SECTION NUMBER. */ +/* Start new data section. sect is the section number. */ L1002: SECT=GETNUM(1); OLDLOC= -1; @@ -221,7 +221,7 @@ L1002: SECT=GETNUM(1); * (10) (11) (12) (13) (14) */ BUG(9); -/* SECTIONS 1, 2, 5, 6, 10, 14. READ MESSAGES AND SET UP POINTERS. */ +/* Sections 1, 2, 5, 6, 10, 14. Read messages and set up pointers. */ L1004: KK=LINUSE; L1005: LINUSE=KK; @@ -269,11 +269,11 @@ L1014: TRNVLS=TRNVLS+1; 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. */ +/* 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; @@ -291,12 +291,12 @@ L1035: L=GETNUM(0); 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.) */ +/* 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++) { @@ -307,9 +307,9 @@ 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. */ +/* 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; @@ -317,14 +317,14 @@ L1050: OBJ=GETNUM(1); FIXD[OBJ]=GETNUM(0); goto L1050; -/* READ DEFAULT MESSAGE NUMBERS FOR ACTION VERBS, STORE IN ACTSPK. */ +/* 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. */ +/* Read info about available liquids and other conditions, store in COND. */ L1070: K=GETNUM(1); if(K == -1) goto L1002; @@ -334,7 +334,7 @@ L1071: LOC=GETNUM(0); COND[LOC]=COND[LOC]+SETBIT(K); goto L1071; -/* READ DATA FOR HINTS. */ +/* Read data for hints. */ L1080: HNTMAX=0; L1081: K=GETNUM(1); @@ -346,7 +346,7 @@ L1083: HINTS[K][I] =GETNUM(0); HNTMAX=(HNTMAX>K ? HNTMAX : K); goto L1081; -/* READ THE SOUND/TEXT INFO, STORE IN OBJSND, OBJTXT, LOCSND. */ +/* Read the sound/text info, store in OBJSND, OBJTXT, LOCSND. */ L1090: K=GETNUM(1); if(K == -1) goto L1002; @@ -361,15 +361,15 @@ L1092: LOCSND[K]=KK; goto L1090; } -/* FINISH CONSTRUCTING INTERNAL DATA FORMAT */ +/* 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. */ +/* 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 modulo 5 unless "LOOK" is used. */ static int finish_init(void) { /* 1101 */ for (I=1; I<=100; I++) { @@ -387,12 +387,12 @@ L1101: {long x = I+100; LINK[x]=0;} 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. */ +/* 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; @@ -408,10 +408,10 @@ L1106: /*etc*/ ; 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. */ +/* 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; @@ -420,15 +420,15 @@ L1107: if(PLAC[K] != 0 && FIXD[K] <= 0)DROP(K,PLAC[K]); 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. */ +/* 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. */ +/* Define some handy mnemonics. these correspond to object numbers. */ AXE=VOCWRD(12405,1); BATTER=VOCWRD(201202005,1); @@ -471,7 +471,7 @@ L1300: HINTLC[I]=0; VOLCAN=VOCWRD(1765120301,1); WATER=VOCWRD(1851200518,1); -/* OBJECTS FROM 50 THROUGH WHATEVER ARE TREASURES. HERE ARE A FEW. */ +/* Objects from 50 through whatever are treasures. Here are a few. */ AMBER=VOCWRD(113020518,1); CHAIN=VOCWRD(308010914,1); @@ -489,7 +489,7 @@ L1300: HINTLC[I]=0; TRIDNT=VOCWRD(2018090405,1); VASE=VOCWRD(22011905,1); -/* THESE ARE MOTION-VERB NUMBERS. */ +/* These are motion-verb numbers. */ BACK=VOCWRD(2010311,0); CAVE=VOCWRD(3012205,0); @@ -500,7 +500,7 @@ L1300: HINTLC[I]=0; NUL=VOCWRD(14211212,0); STREAM=VOCWRD(1920180501,0); -/* AND SOME ACTION VERBS. */ +/* And some action verbs. */ FIND=VOCWRD(6091404,2); INVENT=VOCWRD(914220514,2); @@ -508,19 +508,19 @@ L1300: HINTLC[I]=0; 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. */ +/* 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; @@ -536,27 +536,27 @@ L1700: DSEEN[I]=false; 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 */ +/* 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; @@ -593,7 +593,7 @@ L1800: {long x = 2*I+81; if(RTEXT[x] != 0)MAXDIE=I+1;} return(0); /* then we won't actually return from initialisation */ } -/* REPORT ON AMOUNT OF ARRAYS ACTUALLY USED, TO PERMIT REDUCTIONS. */ +/* Report on amount of arrays actually used, to permit reductions. */ static void report(void) { /* 1998 */ for (K=1; K<=LOCSIZ; K++) { diff --git a/main.c b/main.c index 9730b7a..08d7092 100644 --- a/main.c +++ b/main.c @@ -50,27 +50,27 @@ extern int action(long); int main(int argc, char *argv[]) { -/* ADVENTURE (REV 2: 20 TREASURES) */ +/* 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 */ +/* 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: +/* 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 */ + * 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 */ +/* Read the database if we have not yet done so */ LINES = (long *)calloc(LINSIZ+1,sizeof(long)); if(!LINES){ @@ -82,17 +82,17 @@ int main(int argc, char *argv[]) { 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. */ +/* 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(0); -/* START-UP, DWARF STUFF */ +/* Start-up, dwarf stuff */ L1: SETUP= -1; I=RAN(-1); @@ -103,7 +103,7 @@ L1: SETUP= -1; LIMIT=330; if(NOVICE)LIMIT=1000; -/* CAN'T LEAVE CAVE ONCE IT'S CLOSING (EXCEPT BY MAIN OFFICE). */ +/* Can't leave cave once it's closing (except by main office). */ L2: if(!OUTSID(NEWLOC) || NEWLOC == 0 || !CLOSNG) goto L71; RSPEAK(130); @@ -111,9 +111,9 @@ L2: if(!OUTSID(NEWLOC) || NEWLOC == 0 || !CLOSNG) goto L71; 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). */ +/* 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++) { @@ -125,23 +125,23 @@ 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. */ +/* 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. */ +/* 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. */ +/* 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; @@ -158,17 +158,17 @@ L6002: ODLOC[I]=DLOC[I]; 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. */ +/* 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. */ +/* Fill TK array with all the places this dwarf might go. */ J=1; KK=DLOC[I]; KK=KEY[KK]; @@ -193,15 +193,15 @@ L6016: TK[J]=ODLOC[I]; 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). */ +/* 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!). */ +/* 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; @@ -212,7 +212,7 @@ L6020: if(HERE(J))K=1; goto L6030; L6021: if(PLACE[CHEST] != 0) goto L6022; -/* INSTALL CHEST ONLY ONCE, TO INSURE IT IS THE LAST TREASURE IN THE LIST. */ +/* Install chest only once, to insure it is the last treasure in the list. */ MOVE(CHEST,CHLOC); MOVE(MESSAG,CHLOC2); L6022: RSPEAK(128); @@ -232,7 +232,7 @@ L6025: RSPEAK(186); MOVE(MESSAG,CHLOC2); goto L6024; -/* THIS THREATENING LITTLE DWARF IS IN THE ROOM WITH HIM! */ +/* This threatening little dwarf is in the room with him! */ L6027: DTOTAL=DTOTAL+1; if(ODLOC[I] != DLOC[I]) goto L6030; @@ -242,9 +242,9 @@ L6027: DTOTAL=DTOTAL+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. */ +/* 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); @@ -266,9 +266,9 @@ L6030: /*etc*/ ; -/* DESCRIBE THE CURRENT LOCATION AND (MAYBE) GET NEXT COMMAND. */ +/* Describe the current location and (maybe) get next command. */ -/* PRINT TEXT FOR CURRENT LOC. */ +/* Print text for current loc. */ L2000: if(LOC == 0) goto L99; KK=STEXT[LOC]; @@ -282,11 +282,11 @@ L2001: if(TOTING(BEAR))RSPEAK(141); 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. */ +/* 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; @@ -300,17 +300,17 @@ L2004: if(I == 0) goto L2012; 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). */ +/* 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); @@ -325,9 +325,9 @@ 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). +/* 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; @@ -339,11 +339,11 @@ L2600: if(COND[LOC] < CONDS) goto L2603; 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). */ +/* 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); @@ -355,8 +355,8 @@ L2605: WZDARK=DARK(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. */ +/* 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; @@ -402,20 +402,20 @@ L2630: I=VOCAB(WD1,-1); case 3: goto L2010; } BUG(22); -/* GET SECOND WORD FOR ANALYSIS. */ +/* Get second word for analysis. */ L2800: WD1=WD2; WD1X=WD2X; WD2=0; goto L2620; -/* GEE, I DON'T UNDERSTAND. */ +/* Gee, I don't understand. */ L3000: SETPRM(1,WD1,WD1X); RSPEAK(254); goto L2600; -/* VERB AND OBJECT ANALYSIS MOVED TO SEPARATE MODULE. */ +/* Verb and object analysis moved to separate module. */ L4000: I=4000; goto Laction; L4090: I=4090; goto Laction; @@ -439,7 +439,7 @@ Laction: } BUG(99); -/* RANDOM INTRANSITIVE VERBS COME HERE. CLEAR OBJ JUST IN CASE (SEE "ATTACK"). +/* Random intransitive verbs come here. Clear obj just in case (see "attack"). */ L8000: SETPRM(1,WD1,WD1X); @@ -447,13 +447,13 @@ L8000: SETPRM(1,WD1,WD1X); OBJ=0; goto L2600; -/* FIGURE OUT THE NEW LOCATION +/* 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.) */ + * 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; @@ -495,17 +495,17 @@ L16: NEWLOC=MOD(LL,1000); 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). */ +/* 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". */ +/* 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; @@ -513,18 +513,18 @@ L30100: NEWLOC=99+100-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. */ +/* 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. */ +/* 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); @@ -549,10 +549,10 @@ L30310: NEWLOC=PLAC[TROLL]+FIXD[TROLL]-LOC; OLDLC2=NEWLOC; goto L99; -/* END OF SPECIALS. */ +/* 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. */ +/* 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; @@ -583,8 +583,8 @@ 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. */ +/* 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; @@ -592,14 +592,14 @@ L30: if(DETAIL < 3)RSPEAK(15); ABB[LOC]=0; goto L2; -/* CAVE. DIFFERENT MESSAGES DEPENDING ON WHETHER ABOVE GROUND. */ +/* 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. */ +/* Non-applicable motion. Various messages depending on word given. */ L50: SPK=12; if(K >= 43 && K <= 50)SPK=52; @@ -616,29 +616,29 @@ L50: SPK=12; -/* "YOU'RE DEAD, JIM." +/* "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. */ + * 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. */ +/* Okay, he's dead. Let's get on with it. */ L99: if(CLOSNG) goto L95; NUMDIE=NUMDIE+1; @@ -659,7 +659,7 @@ L98: /*etc*/ ; OLDLOC=LOC; goto L2000; -/* HE DIED DURING CLOSING TIME. NO RESURRECTION. TALLY UP A DEATH AND EXIT. */ +/* He died during closing time. No resurrection. Tally up a death and exit. */ L95: RSPEAK(131); NUMDIE=NUMDIE+1; @@ -668,13 +668,13 @@ L95: RSPEAK(131); -/* HINTS */ +/* 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. */ +/* 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 @@ -693,7 +693,7 @@ L40010: HINTLC[HINT]=0; L40020: HINTLC[HINT]=0; L40030: goto L2602; -/* NOW FOR THE QUICK TESTS. SEE DATABASE DESCRIPTION FOR ONE-LINE NOTES. */ +/* Now for the quick tests. See database description for one-line notes. */ L40100: if(PROP[GRATE] == 0 && !HERE(KEYS)) goto L40010; goto L40020; @@ -732,37 +732,37 @@ L41000: if(TALLY == 1 && PROP[JADE] < 0) goto L40010; -/* CAVE CLOSING AND SCORING */ +/* 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. */ +/* 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. */ +/* 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; @@ -808,7 +808,7 @@ L11000: PROP[BOTTLE]=PUT(BOTTLE,115,1); OLDLOC=115; NEWLOC=115; -/* LEAVE THE GRATE WITH NORMAL (NON-NEGATIVE) PROPERTY. REUSE SIGN. */ +/* Leave the grate with normal (non-negative) property. reuse sign. */ I=PUT(GRATE,116,0); I=PUT(SIGN,116,0); @@ -830,11 +830,11 @@ L11010: if(TOTING(I))DSTROY(I); 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. */ +/* 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; @@ -856,7 +856,7 @@ L12400: LIMIT= -1; if(HERE(LAMP))RSPEAK(184); goto L19999; -/* OH DEAR, HE'S DISTURBED THE DWARVES. */ +/* Oh dear, he's disturbed the dwarves. */ L18999: RSPEAK(SPK); L19000: RSPEAK(136); diff --git a/misc.c b/misc.c index 15932ec..391b43c 100644 --- a/misc.c +++ b/misc.c @@ -7,14 +7,14 @@ /* hack to ignore GCC Unused Result */ #define IGNORE(r) do{if(r){}}while(0) -/* I/O ROUTINES (SPEAK, PSPEAK, RSPEAK, SETPRM, GETIN, YES) */ +/* I/O routines (SPEAK, PSPEAK, RSPEAK, SETPRM, GETIN, YES) */ #undef SPEAK void fSPEAK(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. */ +/* Print the message which starts at LINES(N). Precede it with a blank line + * unless BLKLIN is false. */ if(N == 0)return; @@ -34,13 +34,13 @@ 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. */ +/* 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; @@ -117,8 +117,8 @@ L40: if(BLANK)TYPE0(); void fPSPEAK(long MSG,long 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). */ +/* 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]; @@ -139,7 +139,7 @@ L9: SPEAK(M); void fRSPEAK(long I) { ; -/* PRINT THE I-TH "RANDOM" MESSAGE (SECTION 6 OF DATABASE). */ +/* Print the I-TH "random" message (section 6 of database). */ if(I != 0)SPEAK(RTEXT[I]); @@ -153,8 +153,8 @@ void fRSPEAK(long I) { void fSETPRM(long FIRST, long P1, long P2) { ; -/* STORES PARAMETERS INTO THE PRMCOM PARMS ARRAY FOR USE BY SPEAK. P1 AND P2 - * ARE STORED INTO PARMS(FIRST) AND PARMS(FIRST+1). */ +/* 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); @@ -174,11 +174,11 @@ void fSETPRM(long FIRST, long P1, long P2) { void fGETIN(long *wORD1, long *wORD1X, long *wORD2, long *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. */ +/* 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(); @@ -209,8 +209,8 @@ long fYES(long X, long Y, long 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. */ +/* 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); @@ -230,25 +230,25 @@ L20: YES=false; -/* LINE-PARSING ROUTINES (GETNUM, GETTXT, MAKEWD, PUTTXT, SHFTXT, TYPE0) +/* 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. */ +/* 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(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. */ +/* 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); @@ -281,13 +281,13 @@ L42: GETNUM=GETNUM*SIGN; long fGETTXT(long SKIP,long ONEWRD, long UPPER, long HASH) { 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. */ +/* 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; @@ -329,12 +329,12 @@ L15: /*etc*/ ; long fMAKEWD(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. */ +/* 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; @@ -358,16 +358,16 @@ L10: MAKEWD=MAKEWD+I*(MOD(L,50)+10); void fPUTTXT(long WORD, long *sTATE, long CASE, long HASH) { 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). */ +/* 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; @@ -403,8 +403,8 @@ L18: W=(W-BYTE*DIV)*64; void fSHFTXT(long FROM, long DELTA) { 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. */ +/* 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; @@ -425,8 +425,8 @@ L2: LNLENG=LNLENG+DELTA; void fTYPE0() { long TEMP; -/* TYPE A BLANK LINE. THIS PROCEDURE IS PROVIDED AS A CONVENIENCE FOR CALLERS - * WHO OTHERWISE HAVE NO USE FOR MAPCOM. */ +/* Type a blank line. This procedure is provided as a convenience for callers + * who otherwise have no use for MAPCOM. */ TEMP=LNLENG; @@ -441,12 +441,12 @@ long TEMP; #define TYPE0() fTYPE0() -/* SUSPEND/RESUME I/O ROUTINES (SAVWDS, SAVARR, SAVWRD) */ +/* Suspend/resume I/O routines (SAVWDS, SAVARR, SAVWRD) */ #undef SAVWDS void fSAVWDS(long *W1, long *W2, long *W3, long *W4, long *W5, long *W6, long *W7) { -/* WRITE OR READ 7 VARIABLES. SEE SAVWRD. */ +/* Write or read 7 variables. See SAVWRD. */ SAVWRD(0,(*W1)); @@ -465,7 +465,7 @@ void fSAVWDS(long *W1, long *W2, long *W3, long *W4, long *W5, long *W6, long *W void fSAVARR(long ARR[], long N) { long I; -/* WRITE OR READ AN ARRAY OF N WORDS. SEE SAVWRD. */ +/* Write or read an array of N words. See SAVWRD. */ /* 1 */ for (I=1; I<=N; I++) { @@ -482,14 +482,14 @@ L1: SAVWRD(0,ARR[I]); void fSAVWRD(long OP, long *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, 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 : @@ -535,7 +535,7 @@ L32: N--; WORD=BUF[N]-CKSUM; N++; -/* DATA STRUC. ROUTINES (VOCAB, DSTROY, JUGGLE, MOVE, PUT, CARRY, DROP, ATDWRF) +/* Data struc. routines (VOCAB, DSTROY, JUGGLE, MOVE, PUT, CARRY, DROP, ATDWRF) */ #undef WORD @@ -544,12 +544,12 @@ L32: N--; WORD=BUF[N]-CKSUM; N++; long fVOCAB(long ID, long 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. */ +/* 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 modulo 1000. */ HASH=10000; /* 1 */ for (I=1; I<=TABSIZ; I++) { @@ -577,7 +577,7 @@ L3: VOCAB=KTAB[I]; void fDSTROY(long OBJECT) { ; -/* PERMANENTLY ELIMINATE "OBJECT" BY MOVING TO A NON-EXISTENT LOCATION. */ +/* Permanently eliminate "OBJECT" by moving to a non-existent location. */ MOVE(OBJECT,0); @@ -591,8 +591,8 @@ void fDSTROY(long OBJECT) { 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. */ +/* 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]; @@ -609,9 +609,9 @@ long I, J; 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. */ +/* 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; @@ -630,8 +630,8 @@ L2: if(FROM > 0 && FROM <= 300)CARRY(OBJECT,FROM); 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. */ +/* 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); @@ -646,9 +646,9 @@ long PUT; 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. */ +/* 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; @@ -673,8 +673,8 @@ L8: LINK[TEMP]=LINK[OBJECT]; 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. */ +/* 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; @@ -695,9 +695,9 @@ L2: if(WHERE <= 0)return; 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). */ +/* 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; @@ -720,13 +720,13 @@ L2: ATDWRF=I; -/* UTILITY ROUTINES (SETBIT, TSTBIT, RAN, RNDVOC, BUG) */ +/* 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. */ +/* Returns 2**bit for use in constructing bit-masks. */ SETBIT=1; @@ -744,7 +744,7 @@ L1: SETBIT=SETBIT+SETBIT; long fTSTBIT(MASK,BIT)long BIT, MASK; { long TSTBIT; -/* RETURNS TRUE IF THE SPECIFIED BIT IS SET IN THE MASK. */ +/* Returns true if the specified bit is set in the mask. */ TSTBIT=MOD(MASK/SETBIT(BIT),2) != 0; @@ -758,10 +758,10 @@ long TSTBIT; 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. */ +/* 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; @@ -783,10 +783,10 @@ L2: R=MOD(R*1093L+221587L,1048576L); 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. */ +/* 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; @@ -815,30 +815,30 @@ L8: ATAB[I]=RNDVOC+J*J; #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 */ +/* 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 %ld. See source code for interpretation.\n", NUM); @@ -849,41 +849,41 @@ void fBUG(NUM)long NUM; { -/* MACHINE DEPENDENT ROUTINES (MAPLIN, TYPE, MPINIT, SAVEIO) */ +/* 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. +/* 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. + * 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. + * 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. */ + * 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(); @@ -907,8 +907,8 @@ 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. */ +/* 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; } @@ -919,9 +919,9 @@ L25: if(INLINE[I] != 0)LNLENG=I; 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. */ +/* 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; @@ -963,7 +963,7 @@ L22: J--; L20: /*etc*/ ; } /* end loop */ MAP1[128]=MAP1[10]; -/* FOR THIS VERSION, TAB (9) MAPS TO SPACE (32), SO DEL (127) USES TAB'S VALUE */ +/* For this version, tab (9) maps to space (32), so del (127) uses tab's value */ MAP1[10]=MAP1[33]; MAP1[11]=MAP1[33]; @@ -983,13 +983,13 @@ L30: if(I >= 64)MAP2[VAL]=(I-64)*('B'-'A')+'@'; 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. */ +/* 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: diff --git a/score.c b/score.c index c8c1b96..e0a5be1 100644 --- a/score.c +++ b/score.c @@ -4,36 +4,36 @@ #include "share.h" /* - * SCORING AND WRAP-UP + * scoring and wrap-up */ void score(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 +/* 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. */ + * 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. */ +/* 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; @@ -46,12 +46,12 @@ L20000: SCORE=0; 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). */ +/* 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; @@ -68,17 +68,17 @@ L20010: /*etc*/ ; if(BONUS == 133)SCORE=SCORE+45; L20020: MXSCOR=MXSCOR+45; -/* DID HE COME TO WITT'S END AS HE SHOULD? */ +/* Did he come to Witt's End as he should? */ if(PLACE[MAGZIN] == 108)SCORE=SCORE+1; MXSCOR=MXSCOR+1; -/* ROUND IT OFF. */ +/* Round it off. */ SCORE=SCORE+2; MXSCOR=MXSCOR+2; -/* DEDUCT FOR HINTS/TURNS/SAVES. HINTS < 4 ARE SPECIAL; SEE DATABASE DESC. */ +/* 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]; @@ -87,11 +87,11 @@ L20030: if(HINTED[I])SCORE=SCORE-HINTS[I][2]; if(CLSHNT)SCORE=SCORE-10; SCORE=SCORE-TRNLUZ-SAVED; -/* RETURN TO SCORE COMMAND IF THAT'S WHERE WE CAME FROM. */ +/* 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. */ +/* 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); -- 2.31.1