PROGRAM ADVENT C ADVENTURES C CURRENT LIMITS: C 750 TRAVEL OPTIONS (TRAVEL, TRVSIZ). C 300 VOCABULARY WORDS (KTAB, ATAB, TABSIZ). C 150 LOCATIONS (LTEXT, STEXT, KEY, COND, ABB, ATLOC, LOCSIZ). C 100 OBJECTS (PLAC, PLACE, FIXD, FIXED, LINK (TWICE), PTEXT, PROP). C 35 "ACTION" VERBS (ACTSPK, VRBSIZ). C 205 RANDOM MESSAGES (RTEXT, RTXSIZ). C 12 DIFFERENT PLAYER CLASSIFICATIONS (CTEXT, CVAL, CLSMAX). C 20 HINTS, LESS 3 (HINTLC, HINTED, HINTS, HNTSIZ). C 35 MAGIC MESSAGES (MTEXT, MAGSIZ). C THERE ARE ALSO LIMITS WHICH CANNOT BE EXCEEDED DUE TO THE STRUCTURE OF C THE DATABASE. (E.G., THE VOCABULARY USES N/1000 TO DETERMINE WORD TYPE, C SO THERE CAN'T BE MORE THAN 1000 WORDS.) THESE UPPER LIMITS ARE: C 1000 NON-SYNONYMOUS VOCABULARY WORDS C 300 LOCATIONS C 100 OBJECTS IMPLICIT INTEGER*2(A-Z) INTEGER*4 TRAVEL,ATAB,NXTLOC,WD1,WD1X,WD2,WD2X,NEWLOC BYTE LINES,STRING LOGICAL DSEEN,BLKLIN,HINTED,YES,START LOGICAL TOTING,HERE,AT,BITSET,DARK,WZDARK,LMWARN,CLOSNG,PANIC, 1 CLOSED,GAVEUP,SCORNG,DEMO,YEA COMMON /TXTCOM/ RTEXT(205),LINES(72),ASCVAR,STRING(20) COMMON /BLKCOM/ BLKLIN COMMON /VOCCOM/ KTAB(300),ATAB(300),TABSIZ COMMON /PLACOM/ ATLOC(150),LINK(200),PLACE(100),FIXED(100),HOLDNG COMMON /PTXCOM/ PTEXT(100) COMMON /ABBCOM/ ABB(150) COMMON /MISCOM/ LINUSE,TRVS,CLSSES,OLDLOC,LOC,CVAL,TK,NEWLOC, 1KEY,PLAC,FIXD,ACTSPK,COND,HINTS,HNTMAX,PROP,TALLY,TALLY2, 2HINTLC,CHLOC,CHLOC2,DSEEN,DFLAG,DLOC,DALTLC,KEYS,LAMP,GRATE, 3CAGE,ROD,ROD2,STEPS,BIRD,DOOR,PILLOW,SNAKE,FISSUR,TABLET, 4CLAM,OYSTER,MAGZIN,DWARF,KNIFE,FOOD,BOTTLE,WATER,OIL,PLANT, 5PLANT2,AXE,MIRROR,DRAGON,CHASM,TROLL,TROLL2,BEAR,MESSAG,VEND, 6BATTER,NUGGET,COINS,CHEST,EGGS,TRIDNT,VASE,EMRALD,PYRAM, 7PEARL,RUG,CHAIN,BACK,LOOK,CAVE,NULL,ENTRNC,DPRSSN,SAY,LOCK, 8THROW,FIND,INVENT,TURNS,LMWARN,IWEST,KNFLOC,DETAIL,ABBNUM, 9NUMDIE,MAXDIE,DKILL,FOOBAR,BONUS,CLOCK1,CLOCK2, 1CLOSNG,PANIC,CLOSED,GAVEUP,SCORNG COMMON /MISC2/ I,RTXSIZ,CLSMAX,MAGSIZ,LOCSIZ,CTEXT,STEXT,LTEXT, 1SECT,TRAVEL,TRVSIZ,TABNDX,OBJ,J,K,VERB,HNTSIZ,MAXTRS, 2HINTED,HNTLOC,KK DIMENSION TRAVEL(750) DIMENSION LTEXT(150),STEXT(150),KEY(150),COND(150) DIMENSION PLAC(100),FIXD(100),PROP(100) DIMENSION ACTSPK(35) DIMENSION CTEXT(12),CVAL(12) DIMENSION HINTLC(20),HINTED(20),HINTS(20,4) DIMENSION TK(20),DSEEN(6),DLOC(6),ODLOC(6),HNAME(4) LINSIZ = 9650 TRVSIZ = 750 TABSIZ = 300 LOCSIZ = 150 VRBSIZ = 35 RTXSIZ = 205 CLSMAX = 12 HNTSIZ = 20 MAGSIZ = 35 SETUP = 0 CALL ERRSET(75,.TRUE.,.FALSE.,.FALSE.,.FALSE.,31000) CALL INIT CALL MAIN END SUBROUTINE A5TOA1(A,B,C,MSG,K) C C IN ORDER TO WORK ON A PDP-11, THIS HAS BEEN CHANGED TO BE C AN A4 TO A1 CONVERSION ROUTINE. C A AND B CONTAIN A 1- TO 8-CHARACTER WORD IN 4A1 FORMAT, C CONTAINS ANOTHER C WORD AND/OR PUNCTUATION. THEY ARE UNPACKED TO ONE CHARACTER PER BYTE IN THE C ARRAY "MSG", WITH EXACTLY ONE BLANK BETWEEN B AND C (OR NONE, IF C 'S 100 C BIT IS OFF). C THE INDEX OF THE LAST NON-BLANK CHAR IN CHARS IS RETURNED IN K. IMPLICIT INTEGER(A-Z) BYTE A(4),B(4),C(8),MSG(20) K = 0 DO 2 I=1,4 IF(A(I).LE.' ') GO TO 6 K = K+1 2 MSG(K) = A(I) DO 4 I=1,4 IF(B(I).LE.' ') GO TO 6 K = K+1 4 MSG(K) = B(I) 6 IF(C(1).LE.' ') RETURN IF(C(1).LT.'A') GO TO 10 !PUNCTUATION K = K+1 MSG(K) = ' ' 10 DO 12 I=1,8 IF(C(I).LE.' ') RETURN K = K+1 12 MSG(K) = C(I) RETURN END FUNCTION VOCAB(ID,INIT) C LOOK UP ID IN THE VOCABULARY (ATAB) AND RETURN ITS "DEFINITION" (KTAB), OR C -1 IF NOT FOUND. IF INIT IS POSITIVE, THIS IS AN INITIALISATION CALL SETTING C UP A KEYWORD VARIABLE, AND NOT FINDING IT CONSTITUTES A BUG. IT ALSO MEANS C THAT ONLY KTAB VALUES WHICH TAKEN OVER 1000 EQUAL INIT MAY BE CONSIDERED. C (THUS "STEPS", WHICH IS A MOTION VERB AS WELL AS AN OBJECT, MAY BE LOCATED C AS AN OBJECT.) AND IT ALSO MEANS THE KTAB VALUE IS TAKEN MOD 1000. IMPLICIT INTEGER(A-Z) INTEGER*4 ATAB,ID,HASH COMMON /VOCCOM/ KTAB(300),ATAB(300),TABSIZ HASH=ID DO 1 I=1,TABSIZ IF(KTAB(I).EQ.-1)GOTO 2 IF(INIT.GE.0.AND.KTAB(I)/1000.NE.INIT)GOTO 1 IF(ATAB(I).EQ.HASH)GOTO 3 1 CONTINUE CALL BUG(21) 2 VOCAB=-1 IF(INIT.LT.0)RETURN TYPE 100,HASH 100 FORMAT(' KEYWORD = ',A4) CALL BUG(5) 3 VOCAB=KTAB(I) IF(INIT.GE.0)VOCAB=MOD(VOCAB,1000) RETURN END SUBROUTINE DSTROY(OBJECT) C PERMANENTLY ELIMINATE "OBJECT" BY MOVING TO A NON-EXISTENT LOCATION. IMPLICIT INTEGER(A-Z) COMMON/PLACOM/ATLOC(150),LINK(200),PLACE(100),FIXED(100),HOLDNG CALL MOVE(OBJECT,0) RETURN ENTRY JUGGLE(OBJECT) C JUGGLE AN OBJECT BY PICKING IT UP AND PUTTING IT DOWN AGAIN, THE PURPOSE C BEING TO GET THE OBJECT TO THE FRONT OF THE CHAIN OF THINGS AT ITS LOC. I=PLACE(OBJECT) J=FIXED(OBJECT) CALL MOVE(OBJECT,I) CALL MOVE(OBJECT+100,J) RETURN ENTRY CARRY(OBJECT,WHERE) C START TOTING AN OBJECT, REMOVING IT FROM THE LIST OF THINGS AT ITS FORMER C LOCATION. INCR HOLDNG UNLESS IT WAS ALREADY BEING TOTED. IF OBJECT>100 C (MOVING "FIXED" SECOND LOC), DON'T CHANGE PLACE OR HOLDNG. IF(OBJECT.GT.100)GOTO 5 IF(PLACE(OBJECT).EQ.-1)RETURN PLACE(OBJECT)=-1 HOLDNG=HOLDNG+1 5 IF(ATLOC(WHERE).NE.OBJECT)GOTO 6 ATLOC(WHERE)=LINK(OBJECT) RETURN 6 TEMP=ATLOC(WHERE) 7 IF(LINK(TEMP).EQ.OBJECT)GOTO 8 TEMP=LINK(TEMP) GOTO 7 8 LINK(TEMP)=LINK(OBJECT) RETURN ENTRY DROP(OBJECT,WHERE) C PLACE AN OBJECT AT A GIVEN LOC, PREFIXING IT ONTO THE ATLOC LIST. DECR C HOLDNG IF THE OBJECT WAS BEING TOTED. IF(OBJECT.GT.100)GOTO 1 IF(PLACE(OBJECT).EQ.-1)HOLDNG=HOLDNG-1 PLACE(OBJECT)=WHERE GOTO 2 1 FIXED(OBJECT-100)=WHERE 2 IF(WHERE.LE.0)RETURN LINK(OBJECT)=ATLOC(WHERE) ATLOC(WHERE)=OBJECT RETURN END SUBROUTINE MOVE(OBJECT,WHERE) C PLACE ANY OBJECT ANYWHERE BY PICKING IT UP AND DROPPING IT. MAY ALREADY BE C TOTING, IN WHICH CASE THE CARRY IS A NO-OP. MUSTN'T PICK UP OBJECTS WHICH C ARE NOT AT ANY LOC, SINCE CARRY WANTS TO REMOVE OBJECTS FROM ATLOC CHAINS. IMPLICIT INTEGER(A-Z) COMMON/PLACOM/ATLOC(150),LINK(200),PLACE(100),FIXED(100),HOLDNG IF(OBJECT.GT.100)GOTO 1 FROM=PLACE(OBJECT) GOTO 2 1 FROM=FIXED(OBJECT-100) 2 IF(FROM.GT.0.AND.FROM.LE.300)CALL CARRY(OBJECT,FROM) CALL DROP(OBJECT,WHERE) RETURN END INTEGER FUNCTION PUT(OBJECT,WHERE,PVAL) C PUT IS THE SAME AS MOVE, EXCEPT IT RETURNS A VALUE USED TO SET UP THE C NEGATED PROP VALUES FOR THE REPOSITORY OBJECTS. IMPLICIT INTEGER(A-Z) CALL MOVE(OBJECT,WHERE) PUT=(-1)-PVAL RETURN END INTEGER FUNCTION RAN(N) IMPLICIT INTEGER(A-Z) CALL TICK(TICKS) RAN = MOD(TICKS,N) RETURN END LOGICAL FUNCTION PCT(N) CALL TICK(ITICK) PCT = 100*ITICK .LE. 59*N RETURN END SUBROUTINE BUG(NUM) IMPLICIT INTEGER(A-Z) C THE FOLLOWING CONDITIONS ARE CURRENTLY CONSIDERED FATAL BUGS. NUMBERS < 20 C ARE DETECTED WHILE READING THE DATABASE; THE OTHERS OCCUR AT "RUN TIME". C 0 MESSAGE LINE > 70 CHARACTERS C 1 NULL LINE IN MESSAGE C 2 TOO MANY WORDS OF MESSAGES C 3 TOO MANY TRAVEL OPTIONS C 4 TOO MANY VOCABULARY WORDS C 5 REQUIRED VOCABULARY WORD NOT FOUND C 6 TOO MANY RTEXT OR MTEXT MESSAGES C 7 TOO MANY HINTS C 8 LOCATION HAS COND BIT BEING SET TWICE C 9 INVALID SECTION NUMBER IN DATABASE C 20 SPECIAL TRAVEL (500>L>300) EXCEEDS GOTO LIST C 21 RAN OFF END OF VOCABULARY TABLE C 22 VOCABULARY TYPE (N/1000) NOT BETWEEN 0 AND 3 C 23 INTRANSITIVE ACTION VERB EXCEEDS GOTO LIST C 24 TRANSITIVE ACTION VERB EXCEEDS GOTO LIST C 25 CONDITIONAL TRAVEL ENTRY WITH NO ALTERNATIVE C 26 LOCATION HAS NO TRAVEL ENTRIES C 27 HINT NUMBER EXCEEDS GOTO LIST C 28 INVALID MONTH RETURNED BY DATE FUNCTION TYPE 1, NUM 1 FORMAT (' FATAL ERROR, SEE SOURCE CODE FOR INTERPRETATION.'/ 1 ' PROBABLY CAUSE: ERRONEOUS INFO IN DATABASE.'/ 2 ' ERROR CODE =',I2/) STOP END SUBROUTINE RSPEAK(RMSG) IMPLICIT INTEGER(A-Z) BYTE LINES COMMON/TXTCOM/RTEXT(205),LINES(72),ASCVAR COMMON/PTXCOM/PTEXT(100) INTEGER*4 W1,W2 EQUIVALENCE (W1,LINES),(W2,LINES(5)) IF(RMSG.EQ.0) RETURN N = RTEXT(RMSG) GO TO 2 ENTRY PSPEAK(PMSG,SKIP) N = PTEXT(PMSG) IF(SKIP.GE.0) N = N + SKIP + 1 20 READ(2'N) LOC,LINES IF(SKIP.LT.0.OR.(LOC.EQ.100*SKIP)) GO TO 4 N = N+1 GO TO 20 ENTRY SPEAK(MSG) N = MSG 2 IF(N.EQ.0)RETURN READ(2'N) LOC,LINES 4 IF((W1.EQ.'>$<').OR.(W2.EQ.'>$<')) RETURN OLDLOC = LOC 6 DO 8 I=72,1,-1 L = I IF(LINES(I) .NE. ' ') GO TO 10 8 CONTINUE 10 TYPE 101, (LINES(I),I=1,L) 101 FORMAT(' ',72A1) READ(2'ASCVAR) LOC,LINES IF(LOC .EQ. OLDLOC) GO TO 6 RETURN END SUBROUTINE GETIN(WORD1,WORD1X,WORD2,WORD2X) C GET A COMMAND FROM THE ADVENTURER. SNARF OUT THE FIRST WORD, PAD IT WITH C BLANKS, AND RETURN IT IN WORD1. CHARS 5 THRU 8 ARE RETURNED IN WORD1X, IN C CASE WE NEED TO PRINT OUT THE WHOLE WORD IN AN ERROR MESSAGE. ANY NUMBER OF C BLANKS MAY FOLLOW THE WORD. IF A SECOND WORD APPEARS, IT IS RETURNED IN C WORD2 (CHARS 5 THRU 8 IN WORD2X), ELSE WORD2 IS SET TO ZERO. IMPLICIT INTEGER(A-V,Y-Z) IMPLICIT INTEGER*4(W) BYTE A(20),C(8) EQUIVALENCE (C,W1),(C(5),W2) 2 ACCEPT 101, A 101 FORMAT(20A1) W1 = ' ' W2 = W1 WORD2 = 0 WORD2X = 0 DO 4 J=1,20 4 IF(A(J).NE.' ') GO TO 6 GO TO 2 !IGNORE BLANK LINE 6 J = J-1 DO 8 I=1,8 J = J+1 IF(J.GT.20) GO TO 10 IF(A(J).EQ.' ') GO TO 10 8 C(I) = A(J) 10 WORD1 = W1 WORD1X = W2 12 IF(J.GE.20) RETURN IF(A(J).EQ.' ') GO TO 14 J = J+1 GO TO 12 14 J = J+1 IF(J.GT.20) RETURN IF(A(J).EQ.' ') GO TO 14 W1 = ' ' W2 = W1 K = 0 JJ = J+7 IF(JJ.GT.20) JJ = 20 DO 16 I=J,JJ K = K+1 IF(A(I).LE.' ') GO TO 18 16 C(K) = A(I) 18 WORD2 = W1 WORD2X = W2 RETURN END LOGICAL FUNCTION YES(X,Y,Z) C PRINT MESSAGE X, WAIT FOR YES/NO ANSWER. IF YES, PRINT Y AND LEAVE YEA C TRUE; IF NO, PRINT Z AND LEAVE YEA FALSE. IMPLICIT INTEGER(A-Z) INTEGER*4 REPLY,JUNK1,JUNK2,JUNK3 1 IF(X.NE.0)CALL RSPEAK(X) CALL GETIN(REPLY,JUNK1,JUNK2,JUNK3) IF(REPLY.EQ.'YES'.OR.REPLY.EQ.'Y')GOTO 10 IF(REPLY.EQ.'NO'.OR.REPLY.EQ.'N')GOTO 20 TYPE 9 9 FORMAT(' PLEASE ANSWER THE QUESTION.') GOTO 1 10 YES=.TRUE. IF(Y.NE.0)CALL RSPEAK(Y) RETURN 20 YES=.FALSE. IF(Z.NE.0)CALL RSPEAK(Z) RETURN END