-#include "misc.h"
-#include "main.h"
-#include "share.h"
-#include "funcs.h"
+#include <unistd.h>
+#include <stdlib.h>
#include <stdio.h>
#include <stdbool.h>
-#define TRUE (0==0)
-#define FALSE (0!=0)
+#include "advent.h"
+#include "database.h"
+#include "newdb.h"
/*
- * 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,
- * 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 */
-
+/* Current limits:
+ * 12600 words of message text (LINES, LINSIZ).
+ * 885 travel options (TRAVEL, TRVSIZ).
+ * 330 vocabulary words (KTAB, ATAB, TABSIZ).
+ * 185 locations (LTEXT, STEXT, KEY, COND, game.abbrev, game.atloc,
+ * LOCSND, LOCSIZ).
+ * 100 objects (PLAC, game.place, FIXD, game.fixed, game.link (twice),
+ * PTEXT, game.prop, OBJSND, OBJTXT).
+ * 35 "action" verbs (ACTSPK, VRBSIZ).
+ * 277 random messages (RTEXT, RTXSIZ).
+ * 12 different player classifications (CTEXT, CVAL, CLSMAX).
+ * 20 hints (game.hintlc, game.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
+ * Note:
+ * - the object count limit has been abstracted as NOBJECTS
+ * - the random message limit has been abstracted as RTXSIZ
+ * - maximum locations limit has been abstracted as LOCSIZ
+ */
-/* DESCRIPTION OF THE DATABASE FORMAT
+/* 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 300<N<=500 N-300 IS USED IN A COMPUTED GOTO TO
- * A SECTION OF SPECIAL CODE.
- * IF N>500 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<M<100 IT IS DONE WITH M% PROBABILITY.
- * IF M=100 UNCONDITIONAL, BUT FORBIDDEN TO DWARVES.
- * IF 100<M<=200 HE MUST BE CARRYING OBJECT M-100.
- * IF 200<M<=300 MUST BE CARRYING OR IN SAME ROOM AS M-200.
- * IF 300<M<=400 PROP(M MOD 100) MUST *NOT* BE 0.
- * IF 400<M<=500 PROP(M MOD 100) MUST *NOT* BE 1.
- * IF 500<M<=600 PROP(M MOD 100) MUST *NOT* BE 2, ETC.
- * IF THE CONDITION (IF ANY) IS NOT MET, THEN THE NEXT *DIFFERENT*
- * "DESTINATION" VALUE IS USED (UNLESS IT FAILS TO MEET *ITS* CONDITIONS,
- * IN WHICH CASE THE NEXT IS FOUND, ETC.). TYPICALLY, THE NEXT DEST WILL
- * BE FOR ONE OF THE SAME VERBS, SO THAT ITS ONLY USE IS AS THE ALTERNATE
- * DESTINATION FOR THOSE VERBS. FOR INSTANCE:
+ * 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 300<N<=500 N-300 is used in a computed goto to
+ * a section of special code.
+ * If N>500 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<M<100 it is done with M% probability.
+ * If M=100 unconditional, but forbidden to dwarves.
+ * If 100<M<=200 he must be carrying object M-100.
+ * If 200<M<=300 must be carrying or in same room as M-200.
+ * If 300<M<=400 game.prop(M % 100) must *not* be 0.
+ * If 400<M<=500 game.prop(M % 100) must *not* be 1.
+ * If 500<M<=600 game.prop(M % 100) must *not* be 2, etc.
+ * If the condition (if any) is not met, then the next *different*
+ * "destination" value is used (unless it fails to meet *its* conditions,
+ * in which case the next is found, etc.). Typically, the next dest will
+ * be for one of the same verbs, so that its only use is as the alternate
+ * destination for those verbs. For instance:
* 15 110022 29 31 34 35 23 43
* 15 14 29
- * THIS SAYS THAT, FROM LOC 15, ANY OF THE VERBS 29, 31, ETC., WILL TAKE
- * HIM TO 22 IF HE'S CARRYING OBJECT 10, AND OTHERWISE WILL GO TO 14.
+ * This says that, from loc 15, any of the verbs 29, 31, etc., will take
+ * him to 22 if he's carrying object 10, and otherwise will go to 14.
* 11 303008 49
* 11 9 50
- * 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 MOD 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 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 game.prop(3)=0, in which
+ * case he goes to 9. Verb 50 takes him to 9 regardless of game.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 ">$<". (The magic value
+ * 100 is now mostly abstracted out as NOBJECTS.)
+ * 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+game.prop(N) is the property message (from section 5) if he
+ * listens to the object, and T+game.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 */
-
-static bool quick_init(void);
-static int raw_init(void);
-static void report(void);
-static void quick_save(void);
-static int finish_init(void);
-static void quick_io(void);
-
-void initialise(void) {
- printf("Initialising...\n");
- if(!quick_init()){raw_init(); report(); quick_save();}
- finish_init();
-}
-
-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). */
-
- /* 1001 */ for (I=1; I<=300; I++) {
- if(I <= 100)PTEXT[I]=0;
- if(I <= RTXSIZ)RTEXT[I]=0;
- if(I <= CLSMAX)CTEXT[I]=0;
- if(I <= 100)OBJSND[I]=0;
- if(I <= 100)OBJTXT[I]=0;
- if(I > LOCSIZ) goto L1001;
- STEXT[I]=0;
- LTEXT[I]=0;
- COND[I]=0;
- KEY[I]=0;
- LOCSND[I]=0;
-L1001: /*etc*/ ;
- } /* end loop */
-
- LINUSE=1;
- TRVS=1;
- CLSSES=0;
- TRNVLS=0;
-
-/* START NEW DATA SECTION. SECT IS THE SECTION NUMBER. */
-
-L1002: SECT=GETNUM(1);
- OLDLOC= -1;
- switch (SECT) { case 0: return(0); case 1: goto L1004; case 2: goto
- L1004; case 3: goto L1030; case 4: goto L1040; case 5: goto L1004;
- case 6: goto L1004; case 7: goto L1050; case 8: goto L1060; case
- 9: goto L1070; case 10: goto L1004; case 11: goto L1080; case 12:
- break; case 13: goto L1090; case 14: goto L1004; }
-/* (0) (1) (2) (3) (4) (5) (6) (7) (8) (9)
- * (10) (11) (12) (13) (14) */
- BUG(9);
-
-/* SECTIONS 1, 2, 5, 6, 10, 14. READ MESSAGES AND SET UP POINTERS. */
-
-L1004: KK=LINUSE;
-L1005: LINUSE=KK;
- LOC=GETNUM(1);
- if(LNLENG >= LNPOSN+70)BUG(0);
- if(LOC == -1) goto L1002;
- if(LNLENG < LNPOSN)BUG(1);
-L1006: KK=KK+1;
- if(KK >= LINSIZ)BUG(2);
- LINES[KK]=GETTXT(FALSE,FALSE,FALSE,KK);
- if(LINES[KK] != -1) goto L1006;
- LINES[LINUSE]=KK;
- if(LOC == OLDLOC) goto L1005;
- OLDLOC=LOC;
- LINES[LINUSE]= -KK;
- if(SECT == 14) goto L1014;
- if(SECT == 10) goto L1012;
- if(SECT == 6) goto L1011;
- if(SECT == 5) goto L1010;
- if(LOC > LOCSIZ)BUG(10);
- if(SECT == 1) goto L1008;
-
- STEXT[LOC]=LINUSE;
- goto L1005;
-
-L1008: LTEXT[LOC]=LINUSE;
- goto L1005;
-
-L1010: if(LOC > 0 && LOC <= 100)PTEXT[LOC]=LINUSE;
- goto L1005;
-
-L1011: if(LOC > RTXSIZ)BUG(6);
- RTEXT[LOC]=LINUSE;
- goto L1005;
-
-L1012: CLSSES=CLSSES+1;
- if(CLSSES > CLSMAX)BUG(11);
- CTEXT[CLSSES]=LINUSE;
- CVAL[CLSSES]=LOC;
- goto L1005;
-
-L1014: TRNVLS=TRNVLS+1;
- if(TRNVLS > TRNSIZ)BUG(11);
- TTEXT[TRNVLS]=LINUSE;
- TRNVAL[TRNVLS]=LOC;
- goto L1005;
-
-/* THE STUFF FOR SECTION 3 IS ENCODED HERE. EACH "FROM-LOCATION" GETS A
- * CONTIGUOUS SECTION OF THE "TRAVEL" ARRAY. EACH ENTRY IN TRAVEL IS
- * NEWLOC*1000 + KEYWORD (FROM SECTION 4, MOTION VERBS), AND IS NEGATED IF
- * THIS IS THE LAST ENTRY FOR THIS LOCATION. KEY(N) IS THE INDEX IN TRAVEL
- * OF THE FIRST OPTION AT LOCATION N. */
-
-L1030: LOC=GETNUM(1);
- if(LOC == -1) goto L1002;
- NEWLOC=GETNUM(0);
- if(KEY[LOC] != 0) goto L1033;
- KEY[LOC]=TRVS;
- goto L1035;
-L1033: TRVS--; TRAVEL[TRVS]= -TRAVEL[TRVS]; TRVS++;
-L1035: L=GETNUM(0);
- if(L == 0) goto L1039;
- TRAVEL[TRVS]=NEWLOC*1000+L;
- TRVS=TRVS+1;
- if(TRVS == TRVSIZ)BUG(3);
- goto L1035;
-L1039: TRVS--; TRAVEL[TRVS]= -TRAVEL[TRVS]; TRVS++;
- goto L1030;
-
-/* HERE WE READ IN THE VOCABULARY. KTAB(N) IS THE WORD NUMBER, ATAB(N) IS
- * THE CORRESPONDING WORD. THE -1 AT THE END OF SECTION 4 IS LEFT IN KTAB
- * AS AN END-MARKER. THE WORDS ARE GIVEN A MINIMAL HASH TO MAKE DECIPHERING
- * THE CORE-IMAGE HARDER. (WE DON'T USE GETTXT'S HASH SINCE THAT WOULD FORCE
- * US TO HASH EACH INPUT LINE TO MAKE COMPARISONS WORK, AND THAT IN TURN
- * WOULD MAKE IT HARDER TO DETECT PARTICULAR INPUT WORDS.) */
-
-L1040: J=10000;
- /* 1042 */ for (TABNDX=1; TABNDX<=TABSIZ; TABNDX++) {
-L1043: KTAB[TABNDX]=GETNUM(1);
- if(KTAB[TABNDX] == -1) goto L1002;
- J=J+7;
-L1042: ATAB[TABNDX]=GETTXT(TRUE,TRUE,TRUE,0)+J*J;
- } /* end loop */
- BUG(4);
-
-/* READ IN THE INITIAL LOCATIONS FOR EACH OBJECT. ALSO THE IMMOVABILITY INFO.
- * PLAC CONTAINS INITIAL LOCATIONS OF OBJECTS. FIXD IS -1 FOR IMMOVABLE
- * OBJECTS (INCLUDING THE SNAKE), OR = SECOND LOC FOR TWO-PLACED OBJECTS. */
-
-L1050: OBJ=GETNUM(1);
- if(OBJ == -1) goto L1002;
- PLAC[OBJ]=GETNUM(0);
- FIXD[OBJ]=GETNUM(0);
- goto L1050;
-
-/* READ DEFAULT MESSAGE NUMBERS FOR ACTION VERBS, STORE IN ACTSPK. */
-
-L1060: VERB=GETNUM(1);
- if(VERB == -1) goto L1002;
- ACTSPK[VERB]=GETNUM(0);
- goto L1060;
-
-/* READ INFO ABOUT AVAILABLE LIQUIDS AND OTHER CONDITIONS, STORE IN COND. */
-
-L1070: K=GETNUM(1);
- if(K == -1) goto L1002;
-L1071: LOC=GETNUM(0);
- if(LOC == 0) goto L1070;
- if(CNDBIT(LOC,K)) BUG(8);
- COND[LOC]=COND[LOC]+SETBIT(K);
- goto L1071;
-
-/* READ DATA FOR HINTS. */
-
-L1080: HNTMAX=0;
-L1081: K=GETNUM(1);
- if(K == -1) goto L1002;
- if(K <= 0 || K > HNTSIZ)BUG(7);
- /* 1083 */ for (I=1; I<=4; I++) {
-L1083: HINTS[K][I] =GETNUM(0);
- } /* end loop */
- HNTMAX=(HNTMAX>K ? HNTMAX : K);
- goto L1081;
-
-/* READ THE SOUND/TEXT INFO, STORE IN OBJSND, OBJTXT, LOCSND. */
-
-L1090: K=GETNUM(1);
- if(K == -1) goto L1002;
- KK=GETNUM(0);
- I=GETNUM(0);
- if(I == 0) goto L1092;
- OBJSND[K]=(KK>0 ? KK : 0);
- OBJTXT[K]=(I>0 ? I : 0);
- goto L1090;
-
-L1092: LOCSND[K]=KK;
- goto L1090;
-}
-
-/* FINISH CONSTRUCTING INTERNAL DATA FORMAT */
-
-/* HAVING READ IN THE DATABASE, CERTAIN THINGS ARE NOW CONSTRUCTED. PROPS ARE
- * SET TO ZERO. WE FINISH SETTING UP COND BY CHECKING FOR FORCED-MOTION TRAVEL
- * ENTRIES. THE PLAC AND FIXD ARRAYS ARE USED TO SET UP ATLOC(N) AS THE FIRST
- * OBJECT AT LOCATION N, AND LINK(OBJ) AS THE NEXT OBJECT AT THE SAME LOCATION
- * AS OBJ. (OBJ>100 INDICATES THAT FIXED(OBJ-100)=LOC; LINK(OBJ) IS STILL THE
- * CORRECT LINK TO USE.) ABB IS ZEROED; IT CONTROLS WHETHER THE ABBREVIATED
- * DESCRIPTION IS PRINTED. COUNTS MOD 5 UNLESS "LOOK" IS USED. */
-
-static int finish_init(void) {
- /* 1101 */ for (I=1; I<=100; I++) {
- PLACE[I]=0;
- PROP[I]=0;
- LINK[I]=0;
-L1101: {long x = I+100; LINK[x]=0;}
- } /* end loop */
-
- /* 1102 */ for (I=1; I<=LOCSIZ; I++) {
- ABB[I]=0;
- if(LTEXT[I] == 0 || KEY[I] == 0) goto L1102;
- K=KEY[I];
- if(MOD(IABS(TRAVEL[K]),1000) == 1)COND[I]=2;
-L1102: ATLOC[I]=0;
- } /* end loop */
-
-/* SET UP THE ATLOC AND LINK ARRAYS AS DESCRIBED ABOVE. WE'LL USE THE DROP
- * SUBROUTINE, WHICH PREFACES NEW OBJECTS ON THE LISTS. SINCE WE WANT THINGS
- * IN THE OTHER ORDER, WE'LL RUN THE LOOP BACKWARDS. IF THE OBJECT IS IN TWO
- * LOCS, WE DROP IT TWICE. THIS ALSO SETS UP "PLACE" AND "FIXED" AS COPIES OF
- * "PLAC" AND "FIXD". ALSO, SINCE TWO-PLACED OBJECTS ARE TYPICALLY BEST
- * DESCRIBED LAST, WE'LL DROP THEM FIRST. */
-
- /* 1106 */ for (I=1; I<=100; I++) {
- K=101-I;
- if(FIXD[K] <= 0) goto L1106;
- DROP(K+100,FIXD[K]);
- DROP(K,PLAC[K]);
-L1106: /*etc*/ ;
- } /* end loop */
-
- /* 1107 */ for (I=1; I<=100; I++) {
- K=101-I;
- FIXED[K]=FIXD[K];
-L1107: if(PLAC[K] != 0 && FIXD[K] <= 0)DROP(K,PLAC[K]);
- } /* end loop */
-
-/* TREASURES, AS NOTED EARLIER, ARE OBJECTS 50 THROUGH MAXTRS (CURRENTLY 79).
- * THEIR PROPS ARE INITIALLY -1, AND ARE SET TO 0 THE FIRST TIME THEY ARE
- * DESCRIBED. TALLY KEEPS TRACK OF HOW MANY ARE NOT YET FOUND, SO WE KNOW
- * WHEN TO CLOSE THE CAVE. */
-
- MAXTRS=79;
- TALLY=0;
- /* 1200 */ for (I=50; I<=MAXTRS; I++) {
- if(PTEXT[I] != 0)PROP[I]= -1;
-L1200: TALLY=TALLY-PROP[I];
- } /* end loop */
-
-/* CLEAR THE HINT STUFF. HINTLC(I) IS HOW LONG HE'S BEEN AT LOC WITH COND BIT
- * I. HINTED(I) IS TRUE IFF HINT I HAS BEEN USED. */
-
- /* 1300 */ for (I=1; I<=HNTMAX; I++) {
- HINTED[I]=FALSE;
-L1300: HINTLC[I]=0;
- } /* end loop */
-
-/* DEFINE SOME HANDY MNEMONICS. THESE CORRESPOND TO OBJECT NUMBERS. */
-
- AXE=VOCWRD(12405,1);
- BATTER=VOCWRD(201202005,1);
- BEAR=VOCWRD(2050118,1);
- BIRD=VOCWRD(2091804,1);
- BLOOD=VOCWRD(212151504,1);
- BOTTLE=VOCWRD(215202012,1);
- CAGE=VOCWRD(3010705,1);
- CAVITY=VOCWRD(301220920,1);
- CHASM=VOCWRD(308011913,1);
- CLAM=VOCWRD(3120113,1);
- DOOR=VOCWRD(4151518,1);
- DRAGON=VOCWRD(418010715,1);
- DWARF=VOCWRD(423011806,1);
- FISSUR=VOCWRD(609191921,1);
- FOOD=VOCWRD(6151504,1);
- GRATE=VOCWRD(718012005,1);
- KEYS=VOCWRD(11052519,1);
- KNIFE=VOCWRD(1114090605,1);
- LAMP=VOCWRD(12011316,1);
- MAGZIN=VOCWRD(1301070126,1);
- MESSAG=VOCWRD(1305191901,1);
- MIRROR=VOCWRD(1309181815,1);
- OGRE=VOCWRD(15071805,1);
- OIL=VOCWRD(150912,1);
- OYSTER=VOCWRD(1525192005,1);
- PILLOW=VOCWRD(1609121215,1);
- PLANT=VOCWRD(1612011420,1);
- PLANT2=PLANT+1;
- RESER=VOCWRD(1805190518,1);
- ROD=VOCWRD(181504,1);
- ROD2=ROD+1;
- SIGN=VOCWRD(19090714,1);
- SNAKE=VOCWRD(1914011105,1);
- STEPS=VOCWRD(1920051619,1);
- TROLL=VOCWRD(2018151212,1);
- TROLL2=TROLL+1;
- URN=VOCWRD(211814,1);
- VEND=VOCWRD(1755140409,1);
- VOLCAN=VOCWRD(1765120301,1);
- WATER=VOCWRD(1851200518,1);
-
-/* OBJECTS FROM 50 THROUGH WHATEVER ARE TREASURES. HERE ARE A FEW. */
-
- AMBER=VOCWRD(113020518,1);
- CHAIN=VOCWRD(308010914,1);
- CHEST=VOCWRD(308051920,1);
- COINS=VOCWRD(315091419,1);
- EGGS=VOCWRD(5070719,1);
- EMRALD=VOCWRD(513051801,1);
- JADE=VOCWRD(10010405,1);
- NUGGET=VOCWRD(7151204,1);
- PEARL=VOCWRD(1605011812,1);
- PYRAM=VOCWRD(1625180113,1);
- RUBY=VOCWRD(18210225,1);
- RUG=VOCWRD(182107,1);
- SAPPH=VOCWRD(1901161608,1);
- TRIDNT=VOCWRD(2018090405,1);
- VASE=VOCWRD(22011905,1);
-
-/* THESE ARE MOTION-VERB NUMBERS. */
-
- BACK=VOCWRD(2010311,0);
- CAVE=VOCWRD(3012205,0);
- DPRSSN=VOCWRD(405161805,0);
- ENTER=VOCWRD(514200518,0);
- ENTRNC=VOCWRD(514201801,0);
- LOOK=VOCWRD(12151511,0);
- NUL=VOCWRD(14211212,0);
- STREAM=VOCWRD(1920180501,0);
-
-/* AND SOME ACTION VERBS. */
-
- FIND=VOCWRD(6091404,2);
- INVENT=VOCWRD(914220514,2);
- LOCK=VOCWRD(12150311,2);
- SAY=VOCWRD(190125,2);
- THROW=VOCWRD(2008181523,2);
-
-/* INITIALISE THE DWARVES. DLOC IS LOC OF DWARVES, HARD-WIRED IN. ODLOC IS
- * PRIOR LOC OF EACH DWARF, INITIALLY GARBAGE. DALTLC IS ALTERNATE INITIAL LOC
- * FOR DWARF, IN CASE ONE OF THEM STARTS OUT ON TOP OF THE ADVENTURER. (NO 2
- * OF THE 5 INITIAL LOCS ARE ADJACENT.) DSEEN IS TRUE IF DWARF HAS SEEN HIM.
- * DFLAG CONTROLS THE LEVEL OF ACTIVATION OF ALL THIS:
- * 0 NO DWARF STUFF YET (WAIT UNTIL REACHES HALL OF MISTS)
- * 1 REACHED HALL OF MISTS, BUT HASN'T MET FIRST DWARF
- * 2 MET FIRST DWARF, OTHERS START MOVING, NO KNIVES THROWN YET
- * 3 A KNIFE HAS BEEN THROWN (FIRST SET ALWAYS MISSES)
- * 3+ DWARVES ARE MAD (INCREASES THEIR ACCURACY)
- * SIXTH DWARF IS SPECIAL (THE PIRATE). HE ALWAYS STARTS AT HIS CHEST'S
- * EVENTUAL LOCATION INSIDE THE MAZE. THIS LOC IS SAVED IN CHLOC FOR REF.
- * THE DEAD END IN THE OTHER MAZE HAS ITS LOC STORED IN CHLOC2. */
-
- CHLOC=114;
- CHLOC2=140;
- /* 1700 */ for (I=1; I<=6; I++) {
-L1700: DSEEN[I]=FALSE;
- } /* end loop */
- DFLAG=0;
- DLOC[1]=19;
- DLOC[2]=27;
- DLOC[3]=33;
- DLOC[4]=44;
- DLOC[5]=64;
- DLOC[6]=CHLOC;
- DALTLC=18;
-
-/* OTHER RANDOM FLAGS AND COUNTERS, AS FOLLOWS:
- * ABBNUM HOW OFTEN WE SHOULD PRINT NON-ABBREVIATED DESCRIPTIONS
- * BONUS USED TO DETERMINE AMOUNT OF BONUS IF HE REACHES CLOSING
- * CLOCK1 NUMBER OF TURNS FROM FINDING LAST TREASURE TILL CLOSING
- * CLOCK2 NUMBER OF TURNS FROM FIRST WARNING TILL BLINDING FLASH
- * CONDS MIN VALUE FOR COND(LOC) IF LOC HAS ANY HINTS
- * DETAIL HOW OFTEN WE'VE SAID "NOT ALLOWED TO GIVE MORE DETAIL"
- * DKILL NUMBER OF DWARVES KILLED (UNUSED IN SCORING, NEEDED FOR MSG)
- * FOOBAR CURRENT PROGRESS IN SAYING "FEE FIE FOE FOO".
- * HOLDNG NUMBER OF OBJECTS BEING CARRIED
- * IGO HOW MANY TIMES HE'S SAID "GO XXX" INSTEAD OF "XXX"
- * IWEST HOW MANY TIMES HE'S SAID "WEST" INSTEAD OF "W"
- * KNFLOC 0 IF NO KNIFE HERE, LOC IF KNIFE HERE, -1 AFTER CAVEAT
- * LIMIT LIFETIME OF LAMP (NOT SET HERE)
- * MAXDIE NUMBER OF REINCARNATION MESSAGES AVAILABLE (UP TO 5)
- * NUMDIE NUMBER OF TIMES KILLED SO FAR
- * THRESH NEXT #TURNS THRESHHOLD (-1 IF NONE)
- * TRNDEX INDEX IN TRNVAL OF NEXT THRESHHOLD (SECTION 14 OF DATABASE)
- * TRNLUZ # POINTS LOST SO FAR DUE TO NUMBER OF TURNS USED
- * TURNS TALLIES HOW MANY COMMANDS HE'S GIVEN (IGNORES YES/NO)
- * LOGICALS WERE EXPLAINED EARLIER */
-
- TURNS=0;
- TRNDEX=1;
- THRESH= -1;
- if(TRNVLS > 0)THRESH=MOD(TRNVAL[1],100000)+1;
- TRNLUZ=0;
- LMWARN=FALSE;
- IGO=0;
- IWEST=0;
- KNFLOC=0;
- DETAIL=0;
- ABBNUM=5;
- /* 1800 */ for (I=0; I<=4; I++) {
-L1800: {long x = 2*I+81; if(RTEXT[x] != 0)MAXDIE=I+1;}
- } /* end loop */
- NUMDIE=0;
- HOLDNG=0;
- DKILL=0;
- FOOBAR=0;
- BONUS=0;
- CLOCK1=30;
- CLOCK2=50;
- CONDS=SETBIT(11);
- SAVED=0;
- CLOSNG=FALSE;
- PANIC=FALSE;
- CLOSED=FALSE;
- CLSHNT=FALSE;
- NOVICE=FALSE;
- SETUP=1;
-
- /* if we can ever think of how, we should save it at this point */
-
- return(0); /* then we won't actually return from initialisation */
-}
-
-/* REPORT ON AMOUNT OF ARRAYS ACTUALLY USED, TO PERMIT REDUCTIONS. */
-
-static void report(void) {
- /* 1998 */ for (K=1; K<=LOCSIZ; K++) {
- KK=LOCSIZ+1-K;
- if(LTEXT[KK] != 0) goto L1997;
-L1998: /*etc*/ ;
- } /* end loop */
-
- OBJ=0;
-L1997: /* 1996 */ for (K=1; K<=100; K++) {
-L1996: if(PTEXT[K] != 0)OBJ=OBJ+1;
- } /* end loop */
-
- /* 1995 */ for (K=1; K<=TABNDX; K++) {
-L1995: if(KTAB[K]/1000 == 2)VERB=KTAB[K]-2000;
- } /* end loop */
-
- /* 1994 */ for (K=1; K<=RTXSIZ; K++) {
- J=RTXSIZ+1-K;
- if(RTEXT[J] != 0) goto L1993;
-L1994: /*etc*/ ;
- } /* end loop */
-
-L1993: SETPRM(1,LINUSE,LINSIZ);
- SETPRM(3,TRVS,TRVSIZ);
- SETPRM(5,TABNDX,TABSIZ);
- SETPRM(7,KK,LOCSIZ);
- SETPRM(9,OBJ,100);
- SETPRM(11,VERB,VRBSIZ);
- SETPRM(13,J,RTXSIZ);
- SETPRM(15,CLSSES,CLSMAX);
- SETPRM(17,HNTMAX,HNTSIZ);
- SETPRM(19,TRNVLS,TRNSIZ);
- RSPEAK(267);
- TYPE0();
-}
-
-static long init_reading, init_cksum;
-static FILE *f;
-
-static void quick_item(long*);
-static void quick_array(long*, long);
-
-static bool quick_init(void) {
- extern char *getenv();
- char *adv = getenv("ADVENTURE");
- f = NULL;
- if(adv)f = fopen(adv,READ_MODE);
- if(f == NULL)f = fopen("adventure.data",READ_MODE);
- if(f == NULL)return(FALSE);
- init_reading = TRUE;
- init_cksum = 1;
- quick_io();
- if(fread(&K,4,1,f) == 1) init_cksum -= K; else init_cksum = 1;
- fclose(f);
- if(init_cksum != 0)printf("Checksum error!\n");
- return(init_cksum == 0);
-}
-
-static void quick_save(void) {
- printf("Writing adventure.data...\n");
- f = fopen("adventure.data",WRITE_MODE);
- if(f == NULL){printf("Can't open file!\n"); return;}
- init_reading = FALSE;
- init_cksum = 1;
- quick_io();
- fwrite(&init_cksum,4,1,f);
- fclose(f);
-}
-
-static void quick_io(void) {
- quick_item(&LINUSE);
- quick_item(&TRVS);
- quick_item(&CLSSES);
- quick_item(&TRNVLS);
- quick_item(&TABNDX);
- quick_item(&HNTMAX);
- quick_array(PTEXT,100);
- quick_array(RTEXT,RTXSIZ);
- quick_array(CTEXT,CLSMAX);
- quick_array(OBJSND,100);
- quick_array(OBJTXT,100);
- quick_array(STEXT,LOCSIZ);
- quick_array(LTEXT,LOCSIZ);
- quick_array(COND,LOCSIZ);
- quick_array(KEY,LOCSIZ);
- quick_array(LOCSND,LOCSIZ);
- quick_array(LINES,LINSIZ);
- quick_array(CVAL,CLSMAX);
- quick_array(TTEXT,TRNSIZ);
- quick_array(TRNVAL,TRNSIZ);
- quick_array(TRAVEL,TRVSIZ);
- quick_array(KTAB,TABSIZ);
- quick_array(ATAB,TABSIZ);
- quick_array(PLAC,100);
- quick_array(FIXD,100);
- quick_array(ACTSPK,VRBSIZ);
- quick_array((long *)HINTS,(HNTMAX+1)*5-1);
-}
-
-static void quick_item(W)long *W; {
- if(init_reading && fread(W,4,1,f) != 1)return;
- init_cksum = MOD(init_cksum*13+(*W),60000000);
- if(!init_reading)fwrite(W,4,1,f);
-}
-
-static void quick_array(A,N)long *A, N; { long I;
- if(init_reading && fread(A,4,N+1,f) != N+1)printf("Read error!\n");
- for(I=1;I<=N;I++)init_cksum = MOD(init_cksum*13+A[I],60000000);
- if(!init_reading && fwrite(A,4,N+1,f)!=N+1)printf("Write error!\n");
+ * %9 = A 9-digit number
+ * %B = Variable number of blanks
+ * %! = The entire message should be suppressed */
+
+void initialise(void)
+{
+ if (oldstyle)
+ printf("Initialising...\n");
+
+ for (int i = 1; i <= NOBJECTS; i++) {
+ game.place[i] = LOC_NOWHERE;
+ game.prop[i] = 0;
+ game.link[i + NOBJECTS] = game.link[i] = 0;
+ }
+
+ for (int i = 1; i <= LOCSIZ; i++) {
+ game.abbrev[i] = 0;
+ if (!(locations[i].description.big == 0 || KEY[i] == 0)) {
+ int k = KEY[i];
+ if (MOD(labs(TRAVEL[k]), 1000) == 1)COND[i] = 2;
+ }
+ game.atloc[i] = 0;
+ }
+
+ /* Set up the game.atloc and game.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 "game.place" and "fixed" as copies of "PLAC" and
+ * "FIXD". Also, since two-placed objects are typically best
+ * described last, we'll drop them first. */
+ for (int i = 1; i <= NOBJECTS; i++) {
+ int k = NOBJECTS + 1 - i;
+ if (FIXD[k] > 0) {
+ DROP(k + NOBJECTS, FIXD[k]);
+ DROP(k, PLAC[k]);
+ }
+ }
+
+ for (int i = 1; i <= NOBJECTS; i++) {
+ int k = NOBJECTS + 1 - i;
+ game.fixed[k] = FIXD[k];
+ if (PLAC[k] != 0 && FIXD[k] <= 0)
+ DROP(k, PLAC[k]);
+ }
+
+ /* Treasures, as noted earlier, are objects MINTRS through MAXTRS
+ * Their props are initially -1, and are set to 0 the first time
+ * they are described. game.tally keeps track of how many are
+ * not yet found, so we know when to close the cave. */
+ game.tally = 0;
+ for (int treasure = MINTRS; treasure <= MAXTRS; treasure++) {
+ if (object_descriptions[treasure].inventory != 0)
+ game.prop[treasure] = -1;
+ game.tally = game.tally - game.prop[treasure];
+ }
+
+ /* Clear the hint stuff. game.hintlc[i] is how long he's been at LOC
+ * with cond bit i. game.hinted[i] is true iff hint i has been
+ * used. */
+ for (int i = 1; i <= HNTMAX; i++) {
+ game.hinted[i] = false;
+ game.hintlc[i] = 0;
+ }
+
+ /* Define some handy mnemonics. These correspond to object numbers. */
+ AXE = VOCWRD(WORD_AXE, 1);
+ BATTERY = VOCWRD(WORD_BATTERY, 1);
+ BEAR = VOCWRD(WORD_BEAR, 1);
+ BIRD = VOCWRD(WORD_BIRD, 1);
+ BLOOD = VOCWRD(WORD_BLOOD, 1);
+ BOTTLE = VOCWRD(WORD_BOTTLE, 1);
+ CAGE = VOCWRD(WORD_CAGE, 1);
+ CAVITY = VOCWRD(WORD_CAVITY, 1);
+ CHASM = VOCWRD(WORD_CHASM, 1);
+ CLAM = VOCWRD(WORD_CLAM, 1);
+ DOOR = VOCWRD(WORD_DOOR, 1);
+ DRAGON = VOCWRD(WORD_DRAGON, 1);
+ DWARF = VOCWRD(WORD_DWARF, 1);
+ FISSURE = VOCWRD(WORD_FISSURE, 1);
+ FOOD = VOCWRD(WORD_FOOD, 1);
+ GRATE = VOCWRD(WORD_GRATE, 1);
+ KEYS = VOCWRD(WORD_KEYS, 1);
+ KNIFE = VOCWRD(WORD_KNIFE, 1);
+ LAMP = VOCWRD(WORD_LAMP, 1);
+ MAGAZINE = VOCWRD(WORD_MAGAZINE, 1);
+ MESSAG = VOCWRD(WORD_MESSAG, 1);
+ MIRROR = VOCWRD(WORD_MIRROR, 1);
+ OGRE = VOCWRD(WORD_OGRE, 1);
+ OIL = VOCWRD(WORD_OIL, 1);
+ OYSTER = VOCWRD(WORD_OYSTER, 1);
+ PILLOW = VOCWRD(WORD_PILLOW, 1);
+ PLANT = VOCWRD(WORD_PLANT, 1);
+ PLANT2 = PLANT + 1;
+ RESER = VOCWRD(WORD_RESER, 1);
+ ROD = VOCWRD(WORD_ROD, 1);
+ ROD2 = ROD + 1;
+ SIGN = VOCWRD(WORD_SIGN, 1);
+ SNAKE = VOCWRD(WORD_SNAKE, 1);
+ STEPS = VOCWRD(WORD_STEPS, 1);
+ TROLL = VOCWRD(WORD_TROLL, 1);
+ TROLL2 = TROLL + 1;
+ URN = VOCWRD(WORD_URN, 1);
+ VEND = VOCWRD(WORD_VEND, 1);
+ VOLCANO = VOCWRD(WORD_VOLCANO, 1);
+ WATER = VOCWRD(WORD_WATER, 1);
+
+ /* Objects from MINTRS through MAXTRS are treasures. Here are a few. */
+ AMBER = VOCWRD(WORD_AMBER, 1);
+ CHAIN = VOCWRD(WORD_CHAIN, 1);
+ CHEST = VOCWRD(WORD_CHEST, 1);
+ COINS = VOCWRD(WORD_COINS, 1);
+ EGGS = VOCWRD(WORD_EGGS, 1);
+ EMERALD = VOCWRD(WORD_EMERALD, 1);
+ JADE = VOCWRD(WORD_JADE, 1);
+ NUGGET = VOCWRD(WORD_NUGGET, 1);
+ PEARL = VOCWRD(WORD_PEARL, 1);
+ PYRAMID = VOCWRD(WORD_PYRAMID, 1);
+ RUBY = VOCWRD(WORD_RUBY, 1);
+ RUG = VOCWRD(WORD_RUG, 1);
+ SAPPH = VOCWRD(WORD_SAPPH, 1);
+ TRIDENT = VOCWRD(WORD_TRIDENT, 1);
+ VASE = VOCWRD(WORD_VASE, 1);
+
+ /* These are motion-verb numbers. */
+ BACK = VOCWRD(WORD_BACK, 0);
+ CAVE = VOCWRD(WORD_CAVE, 0);
+ DPRSSN = VOCWRD(WORD_DPRSSN, 0);
+ ENTER = VOCWRD(WORD_ENTER, 0);
+ ENTRNC = VOCWRD(WORD_ENTRNC, 0);
+ LOOK = VOCWRD(WORD_LOOK, 0);
+ NUL = VOCWRD(WORD_NUL, 0);
+ STREAM = VOCWRD(WORD_STREAM, 0);
+
+ /* And some action verbs. */
+ FIND = VOCWRD(WORD_FIND, 2);
+ INVENT = VOCWRD(WORD_INVENT, 2);
+ LOCK = VOCWRD(WORD_LOCK, 2);
+ SAY = VOCWRD(WORD_SAY, 2);
+ THROW = VOCWRD(WORD_THROW, 2);
+
+ /* Initialise the dwarves. game.dloc is loc of dwarves,
+ * hard-wired in. game.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.) game.dseen is true if
+ * dwarf has seen him. game.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 game.chloc for ref. the dead end in the other maze has its
+ * loc stored in game.chloc2. */
+ game.chloc = LOC_DEADEND12;
+ game.chloc2 = LOC_DEADEND13;
+ for (int i = 1; i <= NDWARVES; i++) {
+ game.dseen[i] = false;
+ }
+ game.dflag = 0;
+ game.dloc[1] = LOC_KINGHALL;
+ game.dloc[2] = LOC_WESTBANK;
+ game.dloc[3] = LOC_Y2;
+ game.dloc[4] = LOC_ALIKE3;
+ game.dloc[5] = LOC_COMPLEX;
+ game.dloc[6] = game.chloc;
+
+ /* Other random flags and counters, as follows:
+ * game.abbnum How often we should print non-abbreviated descriptions
+ * game.bonus Used to determine amount of bonus if he reaches closing
+ * game.clock1 Number of turns from finding last treasure till closing
+ * game.clock2 Number of turns from first warning till blinding flash
+ * game.conds Min value for cond(loc) if loc has any hints
+ * game.detail How often we've said "not allowed to give more detail"
+ * game.dkill # of dwarves killed (unused in scoring, needed for msg)
+ * game.foobar Current progress in saying "FEE FIE FOE FOO".
+ * game.holdng Number of objects being carried
+ * igo How many times he's said "go XXX" instead of "XXX"
+ * game.iwest How many times he's said "west" instead of "w"
+ * game.knfloc 0 if no knife here, loc if knife here, -1 after caveat
+ * game.limit Lifetime of lamp (not set here)
+ * maximum_deaths Number of reincarnation messages available (up to 5)
+ * game.numdie Number of times killed so far
+ * game.trnluz # points lost so far due to number of turns used
+ * game.turns Tallies how many commands he's given (ignores yes/no)
+ * Logicals were explained earlier */
+ game.turns = 0;
+ game.trnluz = 0;
+ game.lmwarn = false;
+ game.iwest = 0;
+ game.knfloc = 0;
+ game.detail = 0;
+ game.abbnum = 5;
+ game.numdie = 0;
+ game.holdng = 0;
+ game.dkill = 0;
+ game.foobar = 0;
+ game.bonus = 0;
+ game.clock1 = 30;
+ game.clock2 = 50;
+ game.conds = SETBIT(11);
+ game.saved = 0;
+ game.closng = false;
+ game.panic = false;
+ game.closed = false;
+ game.clshnt = false;
+ game.novice = false;
+ game.blklin = true;
}