• Contact
  • Journal
  • Home
  • ColossalCave
  • Code350
  • Site
  • Page
  • Amiga
    • Rainbow Islands
      • 1loader-dec
      • 1loader
      • boot
      • orig-boot
      • Journal
  • Arcade
    • Asteroids 80%
      • Hardware
      • RAMUse
      • Code

      • DVG
      • VectorROM

      • Journal
    • Crazy Climber 1%
      • BigSpriteGraphics.pdf
      • Buildings.pdf
      • cclimber.asm
      • CharEnc.inc
      • CrazyClimberMemoryMapInfo.pdf
      • GraphicsAndCharacterAssetInfo.pdf
      • MemoryMap.inc
    • Defender 75%
      • RAMUse
      • Hardware
      • Bank1
      • Bank2
      • Bank3
      • Bank7
      • BankFixed
      • Mapping.txt
      • SoundHardware
      • SoundRAMUse
      • SoundCode
      • Defender-Theory-Early.pdf
      • Defender-Theory-Later.pdf
      • Defender.CPU.jpg
      • Defender.ROM.B&W.jpg
      • Defender.Vid.B&W.jpg
      • SoundROM.txt
    • DonkeyKong
      • Hardware
      • RAMUse
      • Code
    • Frogger (Sound)
      • SoundHardware
      • SoundRAMUse
      • SoundCode

      • Hardware
      • RAMUse
      • Code

      • GFX

      • Journal
    • Galaga 5%
      • CPU1 (Main)
      • CPU2 (Secondary)
      • CPU3 (Sound)
      • GFX1 (Characters)
      • GFX2 (Sprites)
      • PROMcolors
      • PROMpaletteChar
      • PROMpaletteSprite

      • CPU1Fix

      • Journal
    • Moon Patrol 75%
      • Hardware
      • RAMUse
      • Code

      • GFX1 (Text)
      • GFX2 (Sprites)
      • GFX3 (Mountains)
      • GFX4 (Hills)
      • GFX5 (City)
      • ImageBackgroundColors
      • SpriteColors
      • SpriteColorSets
      • TextColors

      • MoonPatrolSound
      • SoundHardware
      • SoundRAMUse
      • SoundCode

      • Journal
    • Omega Race 10%
      • Hardware
      • RAMUse
      • MainBoard

      • SoundHardware
      • SoundRAMUse
      • SoundBoard

      • DVGPROM
      • VectorROM

      • Journal
    • Phoenix 90%
      • Hardware
      • RAMUse
      • Code

      • Background
      • Foreground

      • Journal

      • Scramble HHi
        • phoenixj-func-main2.pdf
        • phoenixj-func-main2.scap
        • phoenixj.asm-may2025.txt
        • phoenixj.asm-may2025.txt.pdf
    • Space Invaders
      • invaders.asm
      • Hardware
      • RAMUse
      • Code

      • Journal
    • The Pit
      • Hardware
      • RAMUse
      • Code
    • Time Pilot (Sound)
      • SoundHardware
      • SoundRAMUse
      • SoundCode

      • Hardware
      • RAMUse
      • Code

      • Journal
    • Sea Wolf 1%
      • Hardware
      • RAMUse
      • Code

      • Journal
    • Scramble 1%
      • SoundHardware
      • SoundRAMUse
      • SoundCode

      • Journal
  • Atari2600
    • Stella (Hardware Info)
    • Asteroids 5%
      • RAMUse
      • Code

      • Journal
    • Battle Zone 1%
      • RAMUse
      • Code

      • Journal
    • Chess 1%
      • RAMUse
      • Code

      • Journal
    • Combat 10%
      • RAMUse
      • Code
      • CodePAL

      • Journal
    • Double Gap
      • Code
      • DoubleGap.asm

      • Journal
    • Entombed 1%
      • RAMUse
      • Code

      • Journal
    • ET 1%
      • RAMUse
      • Code

      • Journal
    • Burger Time 1%
      • RAMUse
      • CodeBank0
      • CodeBank1
      • CodeBank2
      • CodeBank3
      • CodeBank4
      • CodeBank5
      • CodeBank6
      • CodeBank7

      • Journal
    • Missile Command 1%
      • RAMUse
      • Code

      • Journal
    • Space Invaders 1%
      • RAMUse
      • Code

      • Journal
  • ColossalCave
    • CodeOrg
    • DataOrg

    • Code350
    • Data350
  • CoCo
    • Hardware
    • Early Work
    • Pyramid
      • RAMUse
      • Code

      • Journal
    • Raaka Tu
      • RAMUse
      • Code

      • Journal
    • Bedlam
      • RAMUse
      • Code

      • Journal
    • Madness & Minotaur
      • Walk Through
        • after_start.txt
        • after_start.cas
        • after_1.txt
        • after_1.cas
        • after_2.txt
        • after_2.cas
        • after_3.txt
        • after_3.cas
        • after_4.txt
        • after_4.cas
        • after_5.txt
        • after_5.cas
        • after_6.txt
        • after_6.cas
        • after_7.txt
        • after_7.cas
        • after_8.txt
        • after_8.cas
        • after_9.txt
        • after_9.cas
        • after_10.txt
        • after_10.cas
        • after_11.txt
        • after_11.cas
        • after_12.txt
        • after_12.cas
        • after_13.txt
        • after_13.cas
        • after_14.txt
        • after_14.cas
        • after_15.txt
        • after_15.cas
        • after_16.txt
        • after_16.cas
        • after_17.txt
        • after_17.cas
        • after_18.txt
        • after_18.cas
        • after_19.txt
        • after_19.cas
        • after_20.txt
        • after_20.cas
        • after_21.txt
        • after_21.cas
        • after_22.txt
        • after_22.cas
        • after_23.txt
        • after_23.cas
        • after_24.txt
        • after_24.cas
        • after_25.txt
        • after_25.cas
      • RAMUse
      • Code

      • SaveGameViewer

      • Journal
    • Mega-Bug
      • RAMUse
      • Code

      • Journal
    • Popcorn
      • RAMUse
      • Code

      • Journal
    • Daggorath
      • RAMUse
      • Code

      • Level Maps

      • Journal
    • Downland 5%
      • RAMUse
      • Code

      • Journal
    • Audio Analyzer 5%
      • RAMUse
      • Code

      • Journal
    • Doubleback
      • RAMUse
      • Code

      • Journal
  • NES
    • Zelda 5%
      • Hardware
      • RAMUse
      • Bank0
      • Bank1
      • Bank2
      • Bank3
      • Bank4
      • Bank5
      • Bank6
      • Bank7

      • Journal
    • Kid Icarus 1%
      • Hardware
      • RAMUse
      • Bank0
      • Bank1
      • Bank2
      • Bank3
      • Bank4
      • Bank5
      • Bank6
      • Bank7

      • Journal
  • Gameboy
    • Hardware
    • Link's Awakening 1%
      • RAMUse
      • Bank00
      • Bank01
      • Bank02
      • Bank03
      • Bank04
      • Bank05
      • Bank06
      • Bank07
      • Bank08
      • Bank09
      • Bank0A
      • Bank0B
      • Bank0C
      • Bank0D
      • Bank0E
      • Bank0F
      • Bank10
      • Bank11
      • Bank12
      • Bank13
      • Bank14
      • Bank15
      • Bank16
      • Bank17
      • Bank18
      • Bank19
      • Bank1A
      • Bank1B
      • Bank1C
      • Bank1D
      • Bank1E
      • Bank1F

      • Journal
    • Tetris 1%
      • RAMUse
      • Code

      • Journal
  • TRS80
    • HardwareLevel2
    • HardwareLevel1
    • HardwareDisk
    • HauntedHouse
      • RAMUse1
      • Code1
      • RAMUse2
      • Code2

      • Journal
    • Pyramid
      • RAMUse
      • Code

      • RAMUse1
      • Code1

      • Journal
    • RaakaTu
      • RAMUse
      • Code

      • Journal
    • Bedlam
      • RAMUse
      • Code

      • Journal
    • Xenos
      • RAMUse
      • Code
      • Section1
      • Section2
      • Section3
      • Section4
      • Section5
      • Section6
      • Section7
      • Section8
      • Section9
      • SSVDOBJS
      • USVDOBJS

      • Journal
  • Virus
    • Morris Worm 1%
      • Journal
    • Stoned
      • Journal

  • Tools
    • Blend
      • blend.zip

      • Journal
  • Colossal Cave Adventure (350 point version by Don Woods)

Colossal Cave Adventure (350 point version by Don Woods)

C  ADVENTURES

C  CURRENT LIMITS:
C      9650 WORDS OF MESSAGE TEXT (LINES, LINSIZ).
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(A-Z)
      LOGICAL DSEEN,BLKLIN,HINTED,YES,START

      COMMON /TXTCOM/ RTEXT,LINES
      COMMON /BLKCOM/ BLKLIN
      COMMON /VOCCOM/ KTAB,ATAB,TABSIZ
      COMMON /PLACOM/ ATLOC,LINK,PLACE,FIXED,HOLDNG
      COMMON /MTXCOM/ MTEXT
      COMMON /PTXCOM/ PTEXT
      COMMON /ABBCOM/ ABB
      COMMON /WIZCOM/ WKDAY,WKEND,HOLID,HBEGIN,HEND,HNAME,
     1SHORT,MAGIC,MAGNM,LATNCY,SAVED,SAVET,SETUP

      DIMENSION LINES(9650)
      DIMENSION TRAVEL(750)
      DIMENSION KTAB(300),ATAB(300)
      DIMENSION LTEXT(150),STEXT(150),KEY(150),COND(150),ABB(150),
     1ATLOC(150)
      DIMENSION PLAC(100),PLACE(100),FIXD(100),FIXED(100),LINK(200),
     1PTEXT(100),PROP(100)
      DIMENSION ACTSPK(35)
      DIMENSION RTEXT(205)
      DIMENSION CTEXT(12),CVAL(12)
      DIMENSION HINTLC(20),HINTED(20),HINTS(20,4)
      DIMENSION MTEXT(35)
      DIMENSION TK(20),DSEEN(6),DLOC(6),ODLOC(6),HNAME(4)

C
C AVOID MAKING THE COMPILER WORRY ABOUT MODIFYING THE DO INDEX
C
      INTEGER IDONDX
      C  STATEMENT FUNCTIONS
C
C
C  TOTING(OBJ)	= TRUE IF THE OBJ IS BEING CARRIED
C  HERE(OBJ)	= TRUE IF THE OBJ IS AT "LOC" (OR IS BEING CARRIED)
C  AT(OBJ)	= TRUE IF ON EITHER SIDE OF TWO-PLACED OBJECT
C  LIQ(DUMMY)	= OBJECT NUMBER OF LIQUID IN BOTTLE
C  LIQLOC(LOC)	= OBJECT NUMBER OF LIQUID (IF ANY) AT LOC
C  BITSET(L,N)	= TRUE IF COND(L) HAS BIT N SET (BIT 0 IS UNITS BIT)
C  FORCED(LOC)	= TRUE IF LOC MOVES WITHOUT ASKING FOR INPUT (COND=2)
C  DARK(DUMMY)	= TRUE IF LOCATION "LOC" IS DARK
C  PCT(N)       = TRUE N% OF THE TIME (N INTEGER FROM 0 TO 100)
C
C  WZDARK SAYS WHETHER THE LOC HE'S LEAVING WAS DARK
C  LMWARN SAYS WHETHER HE'S BEEN WARNED ABOUT LAMP GOING DIM
C  CLOSNG SAYS WHETHER ITS CLOSING TIME YET
C  PANIC SAYS WHETHER HE'S FOUND OUT HE'S TRAPPED IN THE CAVE
C  CLOSED SAYS WHETHER WE'RE ALL THE WAY CLOSED
C  GAVEUP SAYS WHETHER HE EXITED VIA "QUIT"
C  SCORNG INDICATES TO THE SCORE ROUTINE WHETHER WE'RE DOING A "SCORE" COMMAND
C  DEMO IS TRUE IF THIS IS A PRIME-TIME DEMONSTRATION GAME
C  YEA IS RANDOM YES/NO REPLY

      LOGICAL TOTING,HERE,AT,BITSET,DARK,WZDARK,LMWARN,CLOSNG,PANIC,
     1CLOSED,GAVEUP,SCORNG,DEMO,YEA

      TOTING(OBJ)=PLACE(OBJ).EQ.-1
      HERE(OBJ)=PLACE(OBJ).EQ.LOC.OR.TOTING(OBJ)
      AT(OBJ)=PLACE(OBJ).EQ.LOC.OR.FIXED(OBJ).EQ.LOC
      LIQ2(PBOTL)=(1-PBOTL)*WATER+(PBOTL/2)*(WATER+OIL)
      LIQ(DUMMY)=LIQ2(MAX0(PROP(BOTTLE),-1-PROP(BOTTLE)))
      LIQLOC(LOC)=LIQ2((MOD(COND(LOC)/2*2,8)-5)*MOD(COND(LOC)/4,2)+1)
      BITSET(L,N)=(COND(L).AND.SHIFT(1,N)).NE.0
      FORCED(LOC)=COND(LOC).EQ.2
      DARK(DUMMY)=MOD(COND(LOC),2).EQ.0.AND.(PROP(LAMP).EQ.0.OR.
     1.NOT.HERE(LAMP))
      PCT(N)=RAN(100).LT.N
C
      DATA LINSIZ/9650/,TRVSIZ/750/,TABSIZ/300/,LOCSIZ/150/,
     1VRBSIZ/35/,RTXSIZ/205/,CLSMAX/12/,HNTSIZ/20/,MAGSIZ/35/
      DATA SETUP/0/,BLKLIN/.TRUE./
      C  DESCRIPTION OF THE DATABASE FORMAT
C
C
C  THE DATA FILE CONTAINS SEVERAL SECTIONS.  EACH BEGINS WITH A LINE CONTAINING
C  A NUMBER IDENTIFYING THE SECTION, AND ENDS WITH A LINE CONTAINING "-1".
C
C  SECTION 1: LONG FORM DESCRIPTIONS.  EACH LINE CONTAINS A LOCATION NUMBER,
C	A TAB, AND A LINE OF TEXT.  THE SET OF (NECESSARILY ADJACENT) LINES
C	WHOSE NUMBERS ARE X FORM THE LONG DESCRIPTION OF LOCATION X.
C  SECTION 2: SHORT FORM DESCRIPTIONS.  SAME FORMAT AS LONG FORM.  NOT ALL
C	PLACES HAVE SHORT DESCRIPTIONS.
C  SECTION 3: TRAVEL TABLE.  EACH LINE CONTAINS A LOCATION NUMBER (X), A SECOND
C	LOCATION NUMBER (Y), AND A LIST OF MOTION NUMBERS (SEE SECTION 4).
C	EACH MOTION REPRESENTS A VERB WHICH WILL GO TO Y IF CURRENTLY AT X.
C	Y, IN TURN, IS INTERPRETED AS FOLLOWS.  LET M=Y/1000, N=Y MOD 1000.
C		IF N<=300	IT IS THE LOCATION TO GO TO.
C		IF 300<N<=500	N-300 IS USED IN A COMPUTED GOTO TO
C					A SECTION OF SPECIAL CODE.
C		IF N>500	MESSAGE N-500 FROM SECTION 6 IS PRINTED,
C					AND HE STAYS WHEREVER HE IS.
C	MEANWHILE, M SPECIFIES THE CONDITIONS ON THE MOTION.
C		IF M=0		IT'S UNCONDITIONAL.
C		IF 0<M<100	IT IS DONE WITH M% PROBABILITY.
C		IF M=100	UNCONDITIONAL, BUT FORBIDDEN TO DWARVES.
C		IF 100<M<=200	HE MUST BE CARRYING OBJECT M-100.
C		IF 200<M<=300	MUST BE CARRYING OR IN SAME ROOM AS M-200.
C		IF 300<M<=400	PROP(M MOD 100) MUST *NOT* BE 0.
C		IF 400<M<=500	PROP(M MOD 100) MUST *NOT* BE 1.
C		IF 500<M<=600	PROP(M MOD 100) MUST *NOT* BE 2, ETC.
C	IF THE CONDITION (IF ANY) IS NOT MET, THEN THE NEXT *DIFFERENT*
C	"DESTINATION" VALUE IS USED (UNLESS IT FAILS TO MEET *ITS* CONDITIONS,
C	IN WHICH CASE THE NEXT IS FOUND, ETC.).  TYPICALLY, THE NEXT DEST WILL
C	BE FOR ONE OF THE SAME VERBS, SO THAT ITS ONLY USE IS AS THE ALTERNATE
C	DESTINATION FOR THOSE VERBS.  FOR INSTANCE:
C		15	110022	29	31	34	35	23	43
C		15	14	29
C	THIS SAYS THAT, FROM LOC 15, ANY OF THE VERBS 29, 31, ETC., WILL TAKE
C	HIM TO 22 IF HE'S CARRYING OBJECT 10, AND OTHERWISE WILL GO TO 14.
C		11	303008	49
C		11	9	50
C	THIS SAYS THAT, FROM 11, 49 TAKES HIM TO 8 UNLESS PROP(3)=0, IN WHICH
C	CASE HE GOES TO 9.  VERB 50 TAKES HIM TO 9 REGARDLESS OF PROP(3).
C  SECTION 4: VOCABULARY.  EACH LINE CONTAINS A NUMBER (N), A TAB, AND A
C	FIVE-LETTER WORD.  CALL M=N/1000.  IF M=0, THEN THE WORD IS A MOTION
C	VERB FOR USE IN TRAVELLING (SEE SECTION 3).  ELSE, IF M=1, THE WORD IS
C	AN OBJECT.  ELSE, IF M=2, THE WORD IS AN ACTION VERB (SUCH AS "CARRY"
C	OR "ATTACK").  ELSE, IF M=3, THE WORD IS A SPECIAL CASE VERB (SUCH AS
C	"DIG") AND N MOD 1000 IS AN INDEX INTO SECTION 6.  OBJECTS FROM 50 TO
C	(CURRENTLY, ANYWAY) 79 ARE CONSIDERED TREASURES (FOR PIRATE, CLOSEOUT).
C  SECTION 5: OBJECT DESCRIPTIONS.  EACH LINE CONTAINS A NUMBER (N), A TAB,
C	AND A MESSAGE.  IF N IS FROM 1 TO 100, THE MESSAGE IS THE "INVENTORY"
C	MESSAGE FOR OBJECT N.  OTHERWISE, N SHOULD BE 000, 100, 200, ETC., AND
C	THE MESSAGE SHOULD BE THE DESCRIPTION OF THE PRECEDING OBJECT WHEN ITS
C	PROP VALUE IS N/100.  THE N/100 IS USED ONLY TO DISTINGUISH MULTIPLE
C	MESSAGES FROM MULTI-LINE MESSAGES; THE PROP INFO ACTUALLY REQUIRES ALL
C	MESSAGES FOR AN OBJECT TO BE PRESENT AND CONSECUTIVE.  PROPERTIES WHICH
C	PRODUCE NO MESSAGE SHOULD BE GIVEN THE MESSAGE ">$<".
C  SECTION 6: ARBITRARY MESSAGES.  SAME FORMAT AS SECTIONS 1, 2, AND 5, EXCEPT
C	THE NUMBERS BEAR NO RELATION TO ANYTHING (EXCEPT FOR SPECIAL VERBS
C	IN SECTION 4).
C  SECTION 7: OBJECT LOCATIONS.  EACH LINE CONTAINS AN OBJECT NUMBER AND ITS
C	INITIAL LOCATION (ZERO (OR OMITTED) IF NONE).  IF THE OBJECT IS
C	IMMOVABLE, THE LOCATION IS FOLLOWED BY A "-1".  IF IT HAS TWO LOCATIONS
C	(E.G. THE GRATE) THE FIRST LOCATION IS FOLLOWED WITH THE SECOND, AND
C	THE OBJECT IS ASSUMED TO BE IMMOVABLE.
C  SECTION 8: ACTION DEFAULTS.  EACH LINE CONTAINS AN "ACTION-VERB" NUMBER AND
C	THE INDEX (IN SECTION 6) OF THE DEFAULT MESSAGE FOR THE VERB.
C  SECTION 9: LIQUID ASSETS, ETC.  EACH LINE CONTAINS A NUMBER (N) AND UP TO 20
C	LOCATION NUMBERS.  BIT N (WHERE 0 IS THE UNITS BIT) IS SET IN COND(LOC)
C	FOR EACH LOC GIVEN.  THE COND BITS CURRENTLY ASSIGNED ARE:
C		0	LIGHT
C		1	IF BIT 2 IS ON: ON FOR OIL, OFF FOR WATER
C		2	LIQUID ASSET, SEE BIT 1
C		3	PIRATE DOESN'T GO HERE UNLESS FOLLOWING PLAYER
C	OTHER BITS ARE USED TO INDICATE AREAS OF INTEREST TO "HINT" ROUTINES:
C		4	TRYING TO GET INTO CAVE
C		5	TRYING TO CATCH BIRD
C		6	TRYING TO DEAL WITH SNAKE
C		7	LOST IN MAZE
C		8	PONDERING DARK ROOM
C		9	AT WITT'S END
C	COND(LOC) IS SET TO 2, OVERRIDING ALL OTHER BITS, IF LOC HAS FORCED
C	MOTION.
C  SECTION 10: CLASS MESSAGES.  EACH LINE CONTAINS A NUMBER (N), A TAB, AND A
C	MESSAGE DESCRIBING A CLASSIFICATION OF PLAYER.  THE SCORING SECTION
C	SELECTS THE APPROPRIATE MESSAGE, WHERE EACH MESSAGE IS CONSIDERED TO
C	APPLY TO PLAYERS WHOSE SCORES ARE HIGHER THAN THE PREVIOUS N BUT NOT
C	HIGHER THAN THIS N.  NOTE THAT THESE SCORES PROBABLY CHANGE WITH EVERY
C	MODIFICATION (AND PARTICULARLY EXPANSION) OF THE PROGRAM.
C  SECTION 11: HINTS.  EACH LINE CONTAINS A HINT NUMBER (CORRESPONDING TO A
C	COND BIT, SEE SECTION 9), THE NUMBER OF TURNS HE MUST BE AT THE RIGHT
C	LOC(S) BEFORE TRIGGERING THE HINT, THE POINTS DEDUCTED FOR TAKING THE
C	HINT, THE MESSAGE NUMBER (SECTION 6) OF THE QUESTION, AND THE MESSAGE
C	NUMBER OF THE HINT.  THESE VALUES ARE STASHED IN THE "HINTS" ARRAY.
C	HNTMAX IS SET TO THE MAX HINT NUMBER (<= HNTSIZ).  NUMBERS 1-3 ARE
C	UNUSABLE SINCE COND BITS ARE OTHERWISE ASSIGNED, SO 2 IS USED TO
C	REMEMBER IF HE'S READ THE CLUE IN THE REPOSITORY, AND 3 IS USED TO
C	REMEMBER WHETHER HE ASKED FOR INSTRUCTIONS (GETS MORE TURNS, BUT LOSES
C	POINTS).
C  SECTION 12: MAGIC MESSAGES. IDENTICAL TO SECTION 6 EXCEPT PUT IN A SEPARATE
C	SECTION FOR EASIER REFERENCE.  MAGIC MESSAGES ARE USED BY THE STARTUP,
C	MAINTENANCE MODE, AND RELATED ROUTINES.
C  SECTION 0: END OF DATABASE.
      C  READ THE DATABASE IF WE HAVE NOT YET DONE SO

      IF(SETUP.NE.0)GOTO 1100
      TYPE 1000
1000  FORMAT(' Initializing...')

C  CLEAR OUT THE VARIOUS TEXT-POINTER ARRAYS.  ALL TEXT IS STORED IN ARRAY
C  LINES; EACH LINE IS PRECEDED BY A WORD POINTING TO THE NEXT POINTER (I.E.
C  THE WORD FOLLOWING THE END OF THE LINE).  THE POINTER IS NEGATIVE IF THIS IS
C  FIRST LINE OF A MESSAGE.  THE TEXT-POINTER ARRAYS CONTAIN INDICES OF
C  POINTER-WORDS IN LINES.  STEXT(N) IS SHORT DESCRIPTION OF LOCATION N.
C  LTEXT(N) IS LONG DESCRIPTION.  PTEXT(N) POINTS TO MESSAGE FOR PROP(N)=0.
C  SUCCESSIVE PROP MESSAGES ARE FOUND BY CHASING POINTERS.  RTEXT CONTAINS
C  SECTION 6'S STUFF.  CTEXT(N) POINTS TO A PLAYER-CLASS MESSAGE.  MTEXT IS FOR
C  SECTION 12.  WE ALSO CLEAR COND.  SEE DESCRIPTION OF SECTION 9 FOR DETAILS.

      DO 1001 I=1,300
      IF(I.LE.100)PTEXT(I)=0
      IF(I.LE.RTXSIZ)RTEXT(I)=0
      IF(I.LE.CLSMAX)CTEXT(I)=0
      IF(I.LE.MAGSIZ)MTEXT(I)=0
      IF(I.GT.LOCSIZ)GOTO 1001
      STEXT(I)=0
      LTEXT(I)=0
      COND(I)=0
1001  CONTINUE

      OPEN(UNIT=1,NAME='ADVENT',ACCESS='SEQIN')
      SETUP=1
      LINUSE=1
      TRVS=1
      CLSSES=1

C  START NEW DATA SECTION.  SECT IS THE SECTION NUMBER.

1002  READ(1,1003)SECT
1003  FORMAT(G)
      OLDLOC=-1
      GOTO(1100,1004,1004,1030,1040,1004,1004,1050,1060,1070,1004,
     11080,1004) (SECT+1)
C	      (0)  (1)  (2)  (3)  (4)  (5)  (6)  (7)  (8)  (9)  (10)
C	     (11) (12)
      CALL BUG(9)

C  SECTIONS 1, 2, 5, 6, 10, 12.  READ MESSAGES AND SET UP POINTERS.

1004  READ(1,1005)LOC,(LINES(J),J=LINUSE+1,LINUSE+14),KK
1005  FORMAT(1G,15A5)
      IF(KK.NE.' ')CALL BUG(0)
      IF(LOC.EQ.-1)GOTO 1002
      DO 1006 K=1,14
      KK=LINUSE+15-K
      IF(LINES(KK).NE.' ')GOTO 1007
1006  CONTINUE
      IF(LOC.EQ.0)GOTO 1004
C  ABOVE KLUGE IS TO AVOID F40 BUG IF CRLF BROKEN ACROSS RECORD BOUNDARY
      CALL BUG(1)
1007  LINES(LINUSE)=KK+1
      IF(LOC.EQ.OLDLOC)GOTO 1020
      LINES(LINUSE)=-LINES(LINUSE)
      IF(SECT.EQ.12)GOTO 1013
      IF(SECT.EQ.10)GOTO 1012
      IF(SECT.EQ.6)GOTO 1011
      IF(SECT.EQ.5)GOTO 1010
      IF(SECT.EQ.1)GOTO 1008

      STEXT(LOC)=LINUSE
      GOTO 1020

1008  LTEXT(LOC)=LINUSE
      GOTO 1020

1010  IF(LOC.GT.0.AND.LOC.LE.100)PTEXT(LOC)=LINUSE
      GOTO 1020

1011  IF(LOC.GT.RTXSIZ)CALL BUG(6)
      RTEXT(LOC)=LINUSE
      GOTO 1020

1012  CTEXT(CLSSES)=LINUSE
      CVAL(CLSSES)=LOC
      CLSSES=CLSSES+1
      GOTO 1020

1013  IF(LOC.GT.MAGSIZ)CALL BUG(6)
      MTEXT(LOC)=LINUSE

1020  LINUSE=KK+1
      LINES(LINUSE)=-1
      OLDLOC=LOC
      IF(LINUSE+14.GT.LINSIZ)CALL BUG(2)
      GOTO 1004

C  THE STUFF FOR SECTION 3 IS ENCODED HERE.  EACH "FROM-LOCATION" GETS A
C  CONTIGUOUS SECTION OF THE "TRAVEL" ARRAY.  EACH ENTRY IN TRAVEL IS
C  NEWLOC*1000 + KEYWORD (FROM SECTION 4, MOTION VERBS), AND IS NEGATED IF
C  THIS IS THE LAST ENTRY FOR THIS LOCATION.  KEY(N) IS THE INDEX IN TRAVEL
C  OF THE FIRST OPTION AT LOCATION N.

1030  READ(1,1031)LOC,NEWLOC,TK
1031  FORMAT(99G)
      IF(LOC.EQ.0)GOTO 1030
C  ABOVE KLUGE IS TO AVOID AFOREMENTIONED F40 BUG
      IF(LOC.EQ.-1)GOTO 1002
      IF(KEY(LOC).NE.0)GOTO 1033
      KEY(LOC)=TRVS
      GOTO 1035
1033  TRAVEL(TRVS-1)=-TRAVEL(TRVS-1)
1035  DO 1037 L=1,20
      IF(TK(L).EQ.0)GOTO 1039
      TRAVEL(TRVS)=NEWLOC*1000+TK(L)
      TRVS=TRVS+1
      IF(TRVS.EQ.TRVSIZ)CALL BUG(3)
1037  CONTINUE
1039  TRAVEL(TRVS-1)=-TRAVEL(TRVS-1)
      GOTO 1030

C  HERE WE READ IN THE VOCABULARY.  KTAB(N) IS THE WORD NUMBER, ATAB(N) IS
C  THE CORRESPONDING WORD.  THE -1 AT THE END OF SECTION 4 IS LEFT IN KTAB
C  AS AN END-MARKER.  THE WORDS ARE GIVEN A MINIMAL HASH TO MAKE READING THE
C  CORE-IMAGE HARDER.  NOTE THAT '/7-08' HAD BETTER NOT BE IN THE LIST, SINCE
C  IT COULD HASH TO -1.

1040  DO 1042 TABNDX=1,TABSIZ
1043  READ(1,1041)KTAB(TABNDX),ATAB(TABNDX)
1041  FORMAT(G,A5)
      IF(KTAB(TABNDX).EQ.0)GOTO 1043
C  ABOVE KLUGE IS TO AVOID AFOREMENTIONED F40 BUG
      IF(KTAB(TABNDX).EQ.-1)GOTO 1002
1042  ATAB(TABNDX)=ATAB(TABNDX).XOR.'PHROG'
      CALL BUG(4)

C  READ IN THE INITIAL LOCATIONS FOR EACH OBJECT.  ALSO THE IMMOVABILITY INFO.
C  PLAC CONTAINS INITIAL LOCATIONS OF OBJECTS.  FIXD IS -1 FOR IMMOVABLE
C  OBJECTS (INCLUDING THE SNAKE), OR = SECOND LOC FOR TWO-PLACED OBJECTS.

1050  READ(1,1031)OBJ,J,K
      IF(OBJ.EQ.-1)GOTO 1002
      PLAC(OBJ)=J
      FIXD(OBJ)=K
      GOTO 1050

C  READ DEFAULT MESSAGE NUMBERS FOR ACTION VERBS, STORE IN ACTSPK.

1060  READ(1,1031)VERB,J
      IF(VERB.EQ.-1)GOTO 1002
      ACTSPK(VERB)=J
      GOTO 1060

C  READ INFO ABOUT AVAILABLE LIQUIDS AND OTHER CONDITIONS, STORE IN COND.

1070  READ(1,1031)K,TK
      IF(K.EQ.-1)GOTO 1002
      DO 1071 I=1,20
      LOC=TK(I)
      IF(LOC.EQ.0)GOTO 1070
      IF(BITSET(LOC,K))CALL BUG(8)
1071  COND(LOC)=COND(LOC)+SHIFT(1,K)
      GOTO 1070

C  READ DATA FOR HINTS.

1080  HNTMAX=0
1081  READ(1,1031)K,TK
      IF(K.EQ.-1)GOTO 1002
      IF(K.EQ.0)GOTO 1081
      IF(K.LT.0.OR.K.GT.HNTSIZ)CALL BUG(7)
      DO 1083 I=1,4
1083  HINTS(K,I)=TK(I)
      HNTMAX=MAX0(HNTMAX,K)
      GOTO 1081
      C  FINISH CONSTRUCTING INTERNAL DATA FORMAT

C  IF SETUP=2 WE DON'T NEED TO DO THIS.  IT'S ONLY NECESSARY IF WE HAVEN'T DONE
C  IT AT ALL OR IF THE PROGRAM HAS BEEN RUN SINCE THEN.

1100  IF(SETUP.EQ.2)GOTO 1
      IF(SETUP.EQ.-1)GOTO 8305

C  HAVING READ IN THE DATABASE, CERTAIN THINGS ARE NOW CONSTRUCTED.  PROPS ARE
C  SET TO ZERO.  WE FINISH SETTING UP COND BY CHECKING FOR FORCED-MOTION TRAVEL
C  ENTRIES.  THE PLAC AND FIXD ARRAYS ARE USED TO SET UP ATLOC(N) AS THE FIRST
C  OBJECT AT LOCATION N, AND LINK(OBJ) AS THE NEXT OBJECT AT THE SAME LOCATION
C  AS OBJ.  (OBJ>100 INDICATES THAT FIXED(OBJ-100)=LOC; LINK(OBJ) IS STILL THE
C  CORRECT LINK TO USE.)  ABB IS ZEROED; IT CONTROLS WHETHER THE ABBREVIATED
C  DESCRIPTION IS PRINTED.  COUNTS MOD 5 UNLESS "LOOK" IS USED.

      DO 1101 I=1,100
      PLACE(I)=0
      PROP(I)=0
      LINK(I)=0
1101  LINK(I+100)=0

      DO 1102 I=1,LOCSIZ
      ABB(I)=0
      IF(LTEXT(I).EQ.0.OR.KEY(I).EQ.0)GOTO 1102
      K=KEY(I)
      IF(MOD(IABS(TRAVEL(K)),1000).EQ.1)COND(I)=2
1102  ATLOC(I)=0

C  SET UP THE ATLOC AND LINK ARRAYS AS DESCRIBED ABOVE.  WE'LL USE THE DROP
C  SUBROUTINE, WHICH PREFACES NEW OBJECTS ON THE LISTS.  SINCE WE WANT THINGS
C  IN THE OTHER ORDER, WE'LL RUN THE LOOP BACKWARDS.  IF THE OBJECT IS IN TWO
C  LOCS, WE DROP IT TWICE.  THIS ALSO SETS UP "PLACE" AND "FIXED" AS COPIES OF
C  "PLAC" AND "FIXD".  ALSO, SINCE TWO-PLACED OBJECTS ARE TYPICALLY BEST
C  DESCRIBED LAST, WE'LL DROP THEM FIRST.

      DO 1106 I=1,100
      K=101-I
      IF(FIXD(K).LE.0)GOTO 1106
      CALL DROP(K+100,FIXD(K))
      CALL DROP(K,PLAC(K))
1106  CONTINUE

      DO 1107 I=1,100
      K=101-I
      FIXED(K)=FIXD(K)
1107  IF(PLAC(K).NE.0.AND.FIXD(K).LE.0)CALL DROP(K,PLAC(K))

C  TREASURES, AS NOTED EARLIER, ARE OBJECTS 50 THROUGH MAXTRS (CURRENTLY 79).
C  THEIR PROPS ARE INITIALLY -1, AND ARE SET TO 0 THE FIRST TIME THEY ARE
C  DESCRIBED.  TALLY KEEPS TRACK OF HOW MANY ARE NOT YET FOUND, SO WE KNOW
C  WHEN TO CLOSE THE CAVE.  TALLY2 COUNTS HOW MANY CAN NEVER BE FOUND (E.G. IF
C  LOST BIRD OR BRIDGE).

      MAXTRS=79
      TALLY=0
      TALLY2=0
      DO 1200 I=50,MAXTRS
      IF(PTEXT(I).NE.0)PROP(I)=-1
1200  TALLY=TALLY-PROP(I)

C  CLEAR THE HINT STUFF.  HINTLC(I) IS HOW LONG HE'S BEEN AT LOC WITH COND BIT
C  I.  HINTED(I) IS TRUE IFF HINT I HAS BEEN USED.

      DO 1300 I=1,HNTMAX
      HINTED(I)=.FALSE.
1300  HINTLC(I)=0

C  DEFINE SOME HANDY MNEMONICS.  THESE CORRESPOND TO OBJECT NUMBERS.

      KEYS=VOCAB(0+'KEYS',1)
      LAMP=VOCAB(0+'LAMP',1)
      GRATE=VOCAB(0+'GRATE',1)
      CAGE=VOCAB(0+'CAGE',1)
      ROD=VOCAB(0+'ROD',1)
      ROD2=ROD+1
      STEPS=VOCAB(0+'STEPS',1)
      BIRD=VOCAB(0+'BIRD',1)
      DOOR=VOCAB(0+'DOOR',1)
      PILLOW=VOCAB(0+'PILLO',1)
      SNAKE=VOCAB(0+'SNAKE',1)
      FISSUR=VOCAB(0+'FISSU',1)
      TABLET=VOCAB(0+'TABLE',1)
      CLAM=VOCAB(0+'CLAM',1)
      OYSTER=VOCAB(0+'OYSTE',1)
      MAGZIN=VOCAB(0+'MAGAZ',1)
      DWARF=VOCAB(0+'DWARF',1)
      KNIFE=VOCAB(0+'KNIFE',1)
      FOOD=VOCAB(0+'FOOD',1)
      BOTTLE=VOCAB(0+'BOTTL',1)
      WATER=VOCAB(0+'WATER',1)
      OIL=VOCAB(0+'OIL',1)
      PLANT=VOCAB(0+'PLANT',1)
      PLANT2=PLANT+1
      AXE=VOCAB(0+'AXE',1)
      MIRROR=VOCAB(0+'MIRRO',1)
      DRAGON=VOCAB(0+'DRAGO',1)
      CHASM=VOCAB(0+'CHASM',1)
      TROLL=VOCAB(0+'TROLL',1)
      TROLL2=TROLL+1
      BEAR=VOCAB(0+'BEAR',1)
      MESSAG=VOCAB(0+'MESSA',1)
      VEND=VOCAB(0+'VENDI',1)
      BATTER=VOCAB(0+'BATTE',1)

C  OBJECTS FROM 50 THROUGH WHATEVER ARE TREASURES.  HERE ARE A FEW.

      NUGGET=VOCAB(0+'GOLD',1)
      COINS=VOCAB(0+'COINS',1)
      CHEST=VOCAB(0+'CHEST',1)
      EGGS=VOCAB(0+'EGGS',1)
      TRIDNT=VOCAB(0+'TRIDE',1)
      VASE=VOCAB(0+'VASE',1)
      EMRALD=VOCAB(0+'EMERA',1)
      PYRAM=VOCAB(0+'PYRAM',1)
      PEARL=VOCAB(0+'PEARL',1)
      RUG=VOCAB(0+'RUG',1)
      CHAIN=VOCAB(0+'CHAIN',1)

C  THESE ARE MOTION-VERB NUMBERS.

      BACK=VOCAB(0+'BACK',0)
      LOOK=VOCAB(0+'LOOK',0)
      CAVE=VOCAB(0+'CAVE',0)
      NULL=VOCAB(0+'NULL',0)
      ENTRNC=VOCAB(0+'ENTRA',0)
      DPRSSN=VOCAB(0+'DEPRE',0)

C  AND SOME ACTION VERBS.

      SAY=VOCAB(0+'SAY',2)
      LOCK=VOCAB(0+'LOCK',2)
      THROW=VOCAB(0+'THROW',2)
      FIND=VOCAB(0+'FIND',2)
      INVENT=VOCAB(0+'INVEN',2)

C  INITIALISE THE DWARVES.  DLOC IS LOC OF DWARVES, HARD-WIRED IN.  ODLOC IS
C  PRIOR LOC OF EACH DWARF, INITIALLY GARBAGE.  DALTLC IS ALTERNATE INITIAL LOC
C  FOR DWARF, IN CASE ONE OF THEM STARTS OUT ON TOP OF THE ADVENTURER.  (NO 2
C  OF THE 5 INITIAL LOCS ARE ADJACENT.)  DSEEN IS TRUE IF DWARF HAS SEEN HIM.
C  DFLAG CONTROLS THE LEVEL OF ACTIVATION OF ALL THIS:
C	0	NO DWARF STUFF YET (WAIT UNTIL REACHES HALL OF MISTS)
C	1	REACHED HALL OF MISTS, BUT HASN'T MET FIRST DWARF
C	2	MET FIRST DWARF, OTHERS START MOVING, NO KNIVES THROWN YET
C	3	A KNIFE HAS BEEN THROWN (FIRST SET ALWAYS MISSES)
C	3+	DWARVES ARE MAD (INCREASES THEIR ACCURACY)
C  SIXTH DWARF IS SPECIAL (THE PIRATE).  HE ALWAYS STARTS AT HIS CHEST'S
C  EVENTUAL LOCATION INSIDE THE MAZE.  THIS LOC IS SAVED IN CHLOC FOR REF.
C  THE DEAD END IN THE OTHER MAZE HAS ITS LOC STORED IN CHLOC2.

      CHLOC=114
      CHLOC2=140
      DO 1700 I=1,6
1700  DSEEN(I)=.FALSE.
      DFLAG=0
      DLOC(1)=19
      DLOC(2)=27
      DLOC(3)=33
      DLOC(4)=44
      DLOC(5)=64
      DLOC(6)=CHLOC
      DALTLC=18

C  OTHER RANDOM FLAGS AND COUNTERS, AS FOLLOWS:
C	TURNS	TALLIES HOW MANY COMMANDS HE'S GIVEN (IGNORES YES/NO)
C	LIMIT	LIFETIME OF LAMP (NOT SET HERE)
C	IWEST	HOW MANY TIMES HE'S SAID "WEST" INSTEAD OF "W"
C	KNFLOC	0 IF NO KNIFE HERE, LOC IF KNIFE HERE, -1 AFTER CAVEAT
C	DETAIL	HOW OFTEN WE'VE SAID "NOT ALLOWED TO GIVE MORE DETAIL"
C	ABBNUM	HOW OFTEN WE SHOULD PRINT NON-ABBREVIATED DESCRIPTIONS
C	MAXDIE	NUMBER OF REINCARNATION MESSAGES AVAILABLE (UP TO 5)
C	NUMDIE	NUMBER OF TIMES KILLED SO FAR
C	HOLDNG	NUMBER OF OBJECTS BEING CARRIED
C	DKILL	NUMBER OF DWARVES KILLED (UNUSED IN SCORING, NEEDED FOR MSG)
C	FOOBAR	CURRENT PROGRESS IN SAYING "FEE FIE FOE FOO".
C	BONUS	USED TO DETERMINE AMOUNT OF BONUS IF HE REACHES CLOSING
C	CLOCK1	NUMBER OF TURNS FROM FINDING LAST TREASURE TILL CLOSING
C	CLOCK2	NUMBER OF TURNS FROM FIRST WARNING TILL BLINDING FLASH
C	LOGICALS WERE EXPLAINED EARLIER

      TURNS=0
      LMWARN=.FALSE.
      IWEST=0
      KNFLOC=0
      DETAIL=0
      ABBNUM=5
      DO 1800 I=0,4
1800  IF(RTEXT(2*I+81).NE.0)MAXDIE=I+1
      NUMDIE=0
      HOLDNG=0
      DKILL=0
      FOOBAR=0
      BONUS=0
      CLOCK1=30
      CLOCK2=50
      SAVED=0
      CLOSNG=.FALSE.
      PANIC=.FALSE.
      CLOSED=.FALSE.
      GAVEUP=.FALSE.
      SCORNG=.FALSE.

C  IF SETUP=1, REPORT ON AMOUNT OF ARRAYS ACTUALLY USED, TO PERMIT REDUCTIONS.

      IF(SETUP.NE.1)GOTO 1
      SETUP=2

      DO 1998 K=1,LOCSIZ
      KK=LOCSIZ+1-K
      IF(LTEXT(KK).NE.0)GOTO 1997
1998  CONTINUE

      OBJ=0
1997  DO 1996 K=1,100
1996  IF(PTEXT(K).NE.0)OBJ=OBJ+1

      DO 1995 K=1,TABNDX
1995  IF(KTAB(K)/1000.EQ.2)VERB=KTAB(K)-2000

      DO 1994 K=1,RTXSIZ
      J=RTXSIZ+1-K
      IF(RTEXT(J).NE.0)GOTO 1993
1994  CONTINUE

1993  DO 1992 K=1,MAGSIZ
      I=MAGSIZ+1-K
      IF(MTEXT(I).NE.0)GOTO 1991
1992  CONTINUE

1991  K=100
      TYPE 1999,LINUSE,LINSIZ,TRVS,TRVSIZ,TABNDX,TABSIZ,KK
     1,LOCSIZ,OBJ,K,VERB,VRBSIZ,J,RTXSIZ,CLSSES,CLSMAX
     2,HNTMAX,HNTSIZ,I,MAGSIZ
1999  FORMAT (' Table space used:'/
     1' ',I6,' OF ',I6,' words of messages'/
     2' ',I6,' OF ',I6,' travel options'/
     3' ',I6,' OF ',I6,' vocabulary words'/
     4' ',I6,' OF ',I6,' locations'/
     5' ',I6,' OF ',I6,' objects'/
     6' ',I6,' OF ',I6,' action verbs'/
     7' ',I6,' OF ',I6,' RTEXT messages'/
     8' ',I6,' OF ',I6,' CLASS messages'/
     9' ',I6,' OF ',I6,' hints'/
     1' ',I6,' OF ',I6,' MAGIC messages'/
     2)

C  FINALLY, SINCE WE'RE CLEARLY SETTING THINGS UP FOR THE FIRST TIME...

      CALL POOF
      PAUSE 'INIT Done'
      C  START-UP, DWARF STUFF

1     DEMO=START(0)
      CALL MOTD(.FALSE.)
      I=RAN(1)
      HINTED(3)=YES(65,1,0)
      NEWLOC=1
      SETUP=3
      LIMIT=330
      IF(HINTED(3))LIMIT=1000

C  CAN'T LEAVE CAVE ONCE IT'S CLOSING (EXCEPT BY MAIN OFFICE).

2     IF(NEWLOC.GE.9.OR.NEWLOC.EQ.0.OR..NOT.CLOSNG)GOTO 71
      CALL RSPEAK(130)
      NEWLOC=LOC
      IF(.NOT.PANIC)CLOCK2=15
      PANIC=.TRUE.

C  SEE IF A DWARF HAS SEEN HIM AND HAS COME FROM WHERE HE WANTS TO GO.  IF SO,
C  THE DWARF'S BLOCKING HIS WAY.  IF COMING FROM PLACE FORBIDDEN TO PIRATE
C  (DWARVES ROOTED IN PLACE) LET HIM GET OUT (AND ATTACKED).

71    IF(NEWLOC.EQ.LOC.OR.FORCED(LOC).OR.BITSET(LOC,3))GOTO 74
      DO 73 I=1,5
      IF(ODLOC(I).NE.NEWLOC.OR..NOT.DSEEN(I))GOTO 73
      NEWLOC=LOC
      CALL RSPEAK(2)
      GOTO 74
73    CONTINUE
74    LOC=NEWLOC

C  DWARF STUFF.  SEE EARLIER COMMENTS FOR DESCRIPTION OF VARIABLES.  REMEMBER
C  SIXTH DWARF IS PIRATE AND IS THUS VERY DIFFERENT EXCEPT FOR MOTION RULES.

C  FIRST OFF, DON'T LET THE DWARVES FOLLOW HIM INTO A PIT OR A WALL.  ACTIVATE
C  THE WHOLE MESS THE FIRST TIME HE GETS AS FAR AS THE HALL OF MISTS (LOC 15).
C  IF NEWLOC IS FORBIDDEN TO PIRATE (IN PARTICULAR, IF IT'S BEYOND THE TROLL
C  BRIDGE), BYPASS DWARF STUFF.  THAT WAY PIRATE CAN'T STEAL RETURN TOLL, AND
C  DWARVES CAN'T MEET THE BEAR.  ALSO MEANS DWARVES WON'T FOLLOW HIM INTO DEAD
C  END IN MAZE, BUT C'EST LA VIE.  THEY'LL WAIT FOR HIM OUTSIDE THE DEAD END.

      IF(LOC.EQ.0.OR.FORCED(LOC).OR.BITSET(NEWLOC,3))GOTO 2000
      IF(DFLAG.NE.0)GOTO 6000
      IF(LOC.GE.15)DFLAG=1
      GOTO 2000

C  WHEN WE ENCOUNTER THE FIRST DWARF, WE KILL 0, 1, OR 2 OF THE 5 DWARVES.  IF
C  ANY OF THE SURVIVORS IS AT LOC, REPLACE HIM WITH THE ALTERNATE.

6000  IF(DFLAG.NE.1)GOTO 6010
      IF(LOC.LT.15.OR.PCT(95))GOTO 2000
      DFLAG=2
      DO 6001 I=1,2
      J=1+RAN(5)
C  IF SAVED NOT = -1, HE BYPASSED THE "START" CALL.
6001  IF(PCT(50).AND.SAVED.EQ.-1)DLOC(J)=0
      DO 6002 I=1,5
      IF(DLOC(I).EQ.LOC)DLOC(I)=DALTLC
6002  ODLOC(I)=DLOC(I)
      CALL RSPEAK(3)
      CALL DROP(AXE,LOC)
      GOTO 2000

C  THINGS ARE IN FULL SWING.  MOVE EACH DWARF AT RANDOM, EXCEPT IF HE'S SEEN US
C  HE STICKS WITH US.  DWARVES NEVER GO TO LOCS <15.  IF WANDERING AT RANDOM,
C  THEY DON'T BACK UP UNLESS THERE'S NO ALTERNATIVE.  IF THEY DON'T HAVE TO
C  MOVE, THEY ATTACK.  AND, OF COURSE, DEAD DWARVES DON'T DO MUCH OF ANYTHING.

6010  DTOTAL=0
      ATTACK=0
      STICK=0
      DO 6030 I=1,6
      IF(DLOC(I).EQ.0)GOTO 6030
      J=1
      KK=DLOC(I)
      KK=KEY(KK)
      IF(KK.EQ.0)GOTO 6016
6012  NEWLOC=MOD(IABS(TRAVEL(KK))/1000,1000)
      IF(NEWLOC.GT.300.OR.NEWLOC.LT.15.OR.NEWLOC.EQ.ODLOC(I)
     1.OR.(J.GT.1.AND.NEWLOC.EQ.TK(J-1)).OR.J.GE.20
     2.OR.NEWLOC.EQ.DLOC(I).OR.FORCED(NEWLOC)
     3.OR.(I.EQ.6.AND.BITSET(NEWLOC,3))
     4.OR.IABS(TRAVEL(KK))/1000000.EQ.100)GOTO 6014
      TK(J)=NEWLOC
      J=J+1
6014  KK=KK+1
      IF(TRAVEL(KK-1).GE.0)GOTO 6012
6016  TK(J)=ODLOC(I)
      IF(J.GE.2)J=J-1
      J=1+RAN(J)
      ODLOC(I)=DLOC(I)
      DLOC(I)=TK(J)
      DSEEN(I)=(DSEEN(I).AND.LOC.GE.15)
     1.OR.(DLOC(I).EQ.LOC.OR.ODLOC(I).EQ.LOC)
      IF(.NOT.DSEEN(I))GOTO 6030
      DLOC(I)=LOC
      IF(I.NE.6)GOTO 6027

C  THE PIRATE'S SPOTTED HIM.  HE LEAVES HIM ALONE ONCE WE'VE FOUND CHEST.
C  K COUNTS IF A TREASURE IS HERE.  IF NOT, AND TALLY=TALLY2 PLUS ONE FOR
C  AN UNSEEN CHEST, LET THE PIRATE BE SPOTTED.

      IF(LOC.EQ.CHLOC.OR.PROP(CHEST).GE.0)GOTO 6030
      K=0
      DO 6020 J=50,MAXTRS
C  PIRATE WON'T TAKE PYRAMID FROM PLOVER ROOM OR DARK ROOM (TOO EASY!).
      IF(J.EQ.PYRAM.AND.(LOC.EQ.PLAC(PYRAM)
     1.OR.LOC.EQ.PLAC(EMRALD)))GOTO 6020
      IDONDX=J
      IF(TOTING(IDONDX))GOTO 6022
6020  IF(HERE(IDONDX))K=1
      IF(TALLY.EQ.TALLY2+1.AND.K.EQ.0.AND.PLACE(CHEST).EQ.0
     1.AND.HERE(LAMP).AND.PROP(LAMP).EQ.1)GOTO 6025
      IF(ODLOC(6).NE.DLOC(6).AND.PCT(20))CALL RSPEAK(127)
      GOTO 6030

6022  CALL RSPEAK(128)
C  DON'T STEAL CHEST BACK FROM TROLL!
      IF(PLACE(MESSAG).EQ.0)CALL MOVE(CHEST,CHLOC)
      CALL MOVE(MESSAG,CHLOC2)
      DO 6023 J=50,MAXTRS
      IF(J.EQ.PYRAM.AND.(LOC.EQ.PLAC(PYRAM)
     1.OR.LOC.EQ.PLAC(EMRALD)))GOTO 6023
      IDONDX=J
      IF(AT(IDONDX).AND.FIXED(IDONDX).EQ.0)
     1CALL CARRY(IDONDX,LOC)
      IF(TOTING(IDONDX))CALL DROP(IDONDX,CHLOC)
6023  CONTINUE
6024  DLOC(6)=CHLOC
      ODLOC(6)=CHLOC
      DSEEN(6)=.FALSE.
      GOTO 6030

6025  CALL RSPEAK(186)
      CALL MOVE(CHEST,CHLOC)
      CALL MOVE(MESSAG,CHLOC2)
      GOTO 6024

C  THIS THREATENING LITTLE DWARF IS IN THE ROOM WITH HIM!

6027  DTOTAL=DTOTAL+1
      IF(ODLOC(I).NE.DLOC(I))GOTO 6030
      ATTACK=ATTACK+1
      IF(KNFLOC.GE.0)KNFLOC=LOC
      IF(RAN(1000).LT.95*(DFLAG-2))STICK=STICK+1
6030  CONTINUE

C  NOW WE KNOW WHAT'S HAPPENING.  LET'S TELL THE POOR SUCKER ABOUT IT.

      IF(DTOTAL.EQ.0)GOTO 2000
      IF(DTOTAL.EQ.1)GOTO 75
      TYPE 67,DTOTAL
67    FORMAT(/' There are ',I1,' threatening little dwarves in the'
     1,' room with you.')
      GOTO 77
75    CALL RSPEAK(4)
77    IF(ATTACK.EQ.0)GOTO 2000
      IF(DFLAG.EQ.2)DFLAG=3
C  IF SAVED NOT = -1, HE BYPASSED THE "START" CALL.  DWARVES GET *VERY* MAD!
      IF(SAVED.NE.-1)DFLAG=20
      IF(ATTACK.EQ.1)GOTO 79
      TYPE 78,ATTACK
78    FORMAT(/' ',I1,' of them throw knives at you!')
      K=6
82    IF(STICK.GT.1)GOTO 83
      CALL RSPEAK(K+STICK)
      IF(STICK.EQ.0)GOTO 2000
      GOTO 84
83    TYPE 68,STICK
68    FORMAT(/' ',I1,' of them get you!')
84    OLDLC2=LOC
      GOTO 99

79    CALL RSPEAK(5)
      K=52
      GOTO 82
      C  DESCRIBE THE CURRENT LOCATION AND (MAYBE) GET NEXT COMMAND.

C  PRINT TEXT FOR CURRENT LOC.

2000  IF(LOC.EQ.0)GOTO 99
      KK=STEXT(LOC)
      IF(MOD(ABB(LOC),ABBNUM).EQ.0.OR.KK.EQ.0)KK=LTEXT(LOC)
      IF(FORCED(LOC).OR..NOT.DARK(0))GOTO 2001
      IF(WZDARK.AND.PCT(35))GOTO 90
      KK=RTEXT(16)
2001  IF(TOTING(BEAR))CALL RSPEAK(141)
      CALL SPEAK(KK)
      K=1
      IF(FORCED(LOC))GOTO 8
      IF(LOC.EQ.33.AND.PCT(25).AND..NOT.CLOSNG)CALL RSPEAK(8)

C  PRINT OUT DESCRIPTIONS OF OBJECTS AT THIS LOCATION.  IF NOT CLOSING AND
C  PROPERTY VALUE IS NEGATIVE, TALLY OFF ANOTHER TREASURE.  RUG IS SPECIAL
C  CASE; ONCE SEEN, ITS PROP IS 1 (DRAGON ON IT) TILL DRAGON IS KILLED.
C  SIMILARLY FOR CHAIN; PROP IS INITIALLY 1 (LOCKED TO BEAR).  THESE HACKS
C  ARE BECAUSE PROP=0 IS NEEDED TO GET FULL SCORE.

      IF(DARK(0))GOTO 2012
      ABB(LOC)=ABB(LOC)+1
      I=ATLOC(LOC)
2004  IF(I.EQ.0)GOTO 2012
      OBJ=I
      IF(OBJ.GT.100)OBJ=OBJ-100
      IF(OBJ.EQ.STEPS.AND.TOTING(NUGGET))GOTO 2008
      IF(PROP(OBJ).GE.0)GOTO 2006
      IF(CLOSED)GOTO 2008
      PROP(OBJ)=0
      IF(OBJ.EQ.RUG.OR.OBJ.EQ.CHAIN)PROP(OBJ)=1
      TALLY=TALLY-1
C  IF REMAINING TREASURES TOO ELUSIVE, ZAP HIS LAMP.
      IF(TALLY.EQ.TALLY2.AND.TALLY.NE.0)LIMIT=MIN0(35,LIMIT)
2006  KK=PROP(OBJ)
      IF(OBJ.EQ.STEPS.AND.LOC.EQ.FIXED(STEPS))KK=1
      CALL PSPEAK(OBJ,KK)
2008  I=LINK(I)
      GOTO 2004

2009  K=54
2010  SPK=K
2011  CALL RSPEAK(SPK)

2012  VERB=0
      OBJ=0

C  CHECK IF THIS LOC IS ELIGIBLE FOR ANY HINTS.  IF BEEN HERE LONG ENOUGH,
C  BRANCH TO HELP SECTION (ON LATER PAGE).  HINTS ALL COME BACK HERE EVENTUALLY
C  TO FINISH THE LOOP.  IGNORE "HINTS" < 4 (SPECIAL STUFF, SEE DATABASE NOTES).

2600  DO 2602 HINT=4,HNTMAX
      IF(HINTED(HINT))GOTO 2602
      IDONDX=HINT
      IF(.NOT.BITSET(LOC,IDONDX))HINTLC(HINT)=-1
      HINTLC(HINT)=HINTLC(HINT)+1
      IF(HINTLC(HINT).GE.HINTS(HINT,1))GOTO 40000
2602  CONTINUE

C  KICK THE RANDOM NUMBER GENERATOR JUST TO ADD VARIETY TO THE CHASE.  ALSO,
C  IF CLOSING TIME, CHECK FOR ANY OBJECTS BEING TOTED WITH PROP < 0 AND SET
C  THE PROP TO -1-PROP.  THIS WAY OBJECTS WON'T BE DESCRIBED UNTIL THEY'VE
C  BEEN PICKED UP AND PUT DOWN SEPARATE FROM THEIR RESPECTIVE PILES.  DON'T
C  TICK CLOCK1 UNLESS WELL INTO CAVE (AND NOT AT Y2).

      IF(.NOT.CLOSED)GOTO 2605
      IF(PROP(OYSTER).LT.0.AND.TOTING(OYSTER))
     1CALL PSPEAK(OYSTER,1)
      DO 2604 I=1,100
      IDONDX=I
2604  IF(TOTING(IDONDX).AND.PROP(IDONDX).LT.0)
     1PROP(IDONDX)=-1-PROP(IDONDX)
2605  WZDARK=DARK(0)
      IF(KNFLOC.GT.0.AND.KNFLOC.NE.LOC)KNFLOC=0
      I=RAN(1)
      CALL GETIN(WD1,WD1X,WD2,WD2X)

C  EVERY INPUT, CHECK "FOOBAR" FLAG.  IF ZERO, NOTHING'S GOING ON.  IF POS,
C  MAKE NEG.  IF NEG, HE SKIPPED A WORD, SO MAKE IT ZERO.

2608  FOOBAR=MIN0(0,-FOOBAR)
      IF(TURNS.EQ.0.AND.WD1.EQ.'MAGIC'.AND.WD2.EQ.'MODE')CALL MAINT
      TURNS=TURNS+1
      IF(DEMO.AND.TURNS.GE.SHORT)GOTO 13000
      IF(VERB.EQ.SAY.AND.WD2.NE.0)VERB=0
      IF(VERB.EQ.SAY)GOTO 4090
      IF(TALLY.EQ.0.AND.LOC.GE.15.AND.LOC.NE.33)CLOCK1=CLOCK1-1
      IF(CLOCK1.EQ.0)GOTO 10000
      IF(CLOCK1.LT.0)CLOCK2=CLOCK2-1
      IF(CLOCK2.EQ.0)GOTO 11000
      IF(PROP(LAMP).EQ.1)LIMIT=LIMIT-1
      IF(LIMIT.LE.30.AND.HERE(BATTER).AND.PROP(BATTER).EQ.0
     1.AND.HERE(LAMP))GOTO 12000
      IF(LIMIT.EQ.0)GOTO 12400
      IF(LIMIT.LT.0.AND.LOC.LE.8)GOTO 12600
      IF(LIMIT.LE.30)GOTO 12200
19999 K=43
      IF(LIQLOC(LOC).EQ.WATER)K=70
      IF(WD1.EQ.'ENTER'.AND.(WD2.EQ.'STREA'.OR.WD2.EQ.'WATER'))
     1GOTO 2010
      IF(WD1.EQ.'ENTER'.AND.WD2.NE.0)GOTO 2800
      IF((WD1.NE.'WATER'.AND.WD1.NE.'OIL')
     1.OR.(WD2.NE.'PLANT'.AND.WD2.NE.'DOOR'))GOTO 2610
      IF(AT(VOCAB(WD2,1)))WD2='POUR'
2610  IF(WD1.NE.'WEST')GOTO 2630
      IWEST=IWEST+1
      IF(IWEST.EQ.10)CALL RSPEAK(17)
2630  I=VOCAB(WD1,-1)
      IF(I.EQ.-1)GOTO 3000
      K=MOD(I,1000)
      KQ=I/1000+1
      GOTO (8,5000,4000,2010)KQ
      CALL BUG(22)

C  GET SECOND WORD FOR ANALYSIS.

2800  WD1=WD2
      WD1X=WD2X
      WD2=0
      GOTO 2610

C  GEE, I DON'T UNDERSTAND.

3000  SPK=60
      IF(PCT(20))SPK=61
      IF(PCT(20))SPK=13
      CALL RSPEAK(SPK)
      GOTO 2600

C  ANALYSE A VERB.  REMEMBER WHAT IT WAS, GO BACK FOR OBJECT IF SECOND WORD
C  UNLESS VERB IS "SAY", WHICH SNARFS ARBITRARY SECOND WORD.

4000  VERB=K
      SPK=ACTSPK(VERB)
      IF(WD2.NE.0.AND.VERB.NE.SAY)GOTO 2800
      IF(VERB.EQ.SAY)OBJ=WD2
      IF(OBJ.NE.0)GOTO 4090

C  ANALYSE AN INTRANSITIVE VERB (IE, NO OBJECT GIVEN YET).

4080  GOTO(8010,8000,8000,8040,2009,8040,9070,9080,8000,8000,
     12011,9120,9130,8140,9150,8000,8000,8180,8000,8200,
     28000,9220,9230,8240,8250,8260,8270,8000,8000,8300,
     38310)VERB
C	     TAKE DROP  SAY OPEN NOTH LOCK   ON  OFF WAVE CALM
C	     WALK KILL POUR  EAT DRNK  RUB TOSS QUIT FIND INVN
C	     FEED FILL BLST SCOR  FOO  BRF READ BREK WAKE SUSP
C	     HOUR
      CALL BUG(23)

C  ANALYSE A TRANSITIVE VERB.

4090  GOTO(9010,9020,9030,9040,2009,9040,9070,9080,9090,2011,
     12011,9120,9130,9140,9150,9160,9170,2011,9190,9190,
     29210,9220,9230,2011,2011,2011,9270,9280,9290,2011,
     32011)VERB
C	     TAKE DROP  SAY OPEN NOTH LOCK   ON  OFF WAVE CALM
C	     WALK KILL POUR  EAT DRNK  RUB TOSS QUIT FIND INVN
C	     FEED FILL BLST SCOR  FOO  BRF READ BREK WAKE SUSP
C	     HOUR
      CALL BUG(24)

C  ANALYSE AN OBJECT WORD.  SEE IF THE THING IS HERE, WHETHER WE'VE GOT A VERB
C  YET, AND SO ON.  OBJECT MUST BE HERE UNLESS VERB IS "FIND" OR "INVENT(ORY)"
C  (AND NO NEW VERB YET TO BE ANALYSED).  WATER AND OIL ARE ALSO FUNNY, SINCE
C  THEY ARE NEVER ACTUALLY DROPPED AT ANY LOCATION, BUT MIGHT BE HERE INSIDE
C  THE BOTTLE OR AS A FEATURE OF THE LOCATION.

5000  OBJ=K
      IF(FIXED(K).NE.LOC.AND..NOT.HERE(K))GOTO 5100
5010  IF(WD2.NE.0)GOTO 2800
      IF(VERB.NE.0)GOTO 4090
      CALL A5TOA1(WD1,WD1X,'?',TK,K)
      TYPE 5015,(TK(I),I=1,K)
5015  FORMAT(/' What do you want to do with the ',20A1)
      GOTO 2600

5100  IF(K.NE.GRATE)GOTO 5110
      IF(LOC.EQ.1.OR.LOC.EQ.4.OR.LOC.EQ.7)K=DPRSSN
      IF(LOC.GT.9.AND.LOC.LT.15)K=ENTRNC
      IF(K.NE.GRATE)GOTO 8
5110  IF(K.NE.DWARF)GOTO 5120
      DO 5112 I=1,5
      IF(DLOC(I).EQ.LOC.AND.DFLAG.GE.2)GOTO 5010
5112  CONTINUE
5120  IF((LIQ(0).EQ.K.AND.HERE(BOTTLE)).OR.K.EQ.LIQLOC(LOC))GOTO 5010
      IF(OBJ.NE.PLANT.OR..NOT.AT(PLANT2).OR.PROP(PLANT2).EQ.0)GOTO 5130
      OBJ=PLANT2
      GOTO 5010
5130  IF(OBJ.NE.KNIFE.OR.KNFLOC.NE.LOC)GOTO 5140
      KNFLOC=-1
      SPK=116
      GOTO 2011
5140  IF(OBJ.NE.ROD.OR..NOT.HERE(ROD2))GOTO 5190
      OBJ=ROD2
      GOTO 5010
5190  IF((VERB.EQ.FIND.OR.VERB.EQ.INVENT).AND.WD2.EQ.0)GOTO 5010
      CALL A5TOA1(WD1,WD1X,'here.',TK,K)
      TYPE 5199,(TK(I),I=1,K)
5199  FORMAT(/' I see no ',20A1)
      GOTO 2012
      C  FIGURE OUT THE NEW LOCATION
C
C  GIVEN THE CURRENT LOCATION IN "LOC", AND A MOTION VERB NUMBER IN "K", PUT
C  THE NEW LOCATION IN "NEWLOC".  THE CURRENT LOC IS SAVED IN "OLDLOC" IN CASE
C  HE WANTS TO RETREAT.  THE CURRENT OLDLOC IS SAVED IN OLDLC2, IN CASE HE
C  DIES.  (IF HE DOES, NEWLOC WILL BE LIMBO, AND OLDLOC WILL BE WHAT KILLED
C  HIM, SO WE NEED OLDLC2, WHICH IS THE LAST PLACE HE WAS SAFE.)

8     KK=KEY(LOC)
      NEWLOC=LOC
      IF(KK.EQ.0)CALL BUG(26)
      IF(K.EQ.NULL)GOTO 2
      IF(K.EQ.BACK)GOTO 20
      IF(K.EQ.LOOK)GOTO 30
      IF(K.EQ.CAVE)GOTO 40
      OLDLC2=OLDLOC
      OLDLOC=LOC

9     LL=IABS(TRAVEL(KK))
      IF(MOD(LL,1000).EQ.1.OR.MOD(LL,1000).EQ.K)GOTO 10
      IF(TRAVEL(KK).LT.0)GOTO 50
      KK=KK+1
      GOTO 9

10    LL=LL/1000
11    NEWLOC=LL/1000
      K=MOD(NEWLOC,100)
      IF(NEWLOC.LE.300)GOTO 13
      IF(PROP(K).NE.NEWLOC/100-3)GOTO 16
12    IF(TRAVEL(KK).LT.0)CALL BUG(25)
      KK=KK+1
      NEWLOC=IABS(TRAVEL(KK))/1000
      IF(NEWLOC.EQ.LL)GOTO 12
      LL=NEWLOC
      GOTO 11

13    IF(NEWLOC.LE.100)GOTO 14
      IF(TOTING(K).OR.(NEWLOC.GT.200.AND.AT(K)))GOTO 16
      GOTO 12

14    IF(NEWLOC.NE.0.AND..NOT.PCT(NEWLOC))GOTO 12
16    NEWLOC=MOD(LL,1000)
      IF(NEWLOC.LE.300)GOTO 2
      IF(NEWLOC.LE.500)GOTO 30000
      CALL RSPEAK(NEWLOC-500)
      NEWLOC=LOC
      GOTO 2

C  SPECIAL MOTIONS COME HERE.  LABELLING CONVENTION: STATEMENT NUMBERS NNNXX
C  (XX=00-99) ARE USED FOR SPECIAL CASE NUMBER NNN (NNN=301-500).

30000 NEWLOC=NEWLOC-300
      GOTO (30100,30200,30300)NEWLOC
      CALL BUG(20)

C  TRAVEL 301.  PLOVER-ALCOVE PASSAGE.  CAN CARRY ONLY EMERALD.  NOTE: TRAVEL
C  TABLE MUST INCLUDE "USELESS" ENTRIES GOING THROUGH PASSAGE, WHICH CAN NEVER
C  BE USED FOR ACTUAL MOTION, BUT CAN BE SPOTTED BY "GO BACK".

30100 NEWLOC=99+100-LOC
      IF(HOLDNG.EQ.0.OR.(HOLDNG.EQ.1.AND.TOTING(EMRALD)))GOTO 2
      NEWLOC=LOC
      CALL RSPEAK(117)
      GOTO 2

C  TRAVEL 302.  PLOVER TRANSPORT.  DROP THE EMERALD (ONLY USE SPECIAL TRAVEL IF
C  TOTING IT), SO HE'S FORCED TO USE THE PLOVER-PASSAGE TO GET IT OUT.  HAVING
C  DROPPED IT, GO BACK AND PRETEND HE WASN'T CARRYING IT AFTER ALL.

30200 CALL DROP(EMRALD,LOC)
      GOTO 12

C  TRAVEL 303.  TROLL BRIDGE.  MUST BE DONE ONLY AS SPECIAL MOTION SO THAT
C  DWARVES WON'T WANDER ACROSS AND ENCOUNTER THE BEAR.  (THEY WON'T FOLLOW THE
C  PLAYER THERE BECAUSE THAT REGION IS FORBIDDEN TO THE PIRATE.)  IF
C  PROP(TROLL)=1, HE'S CROSSED SINCE PAYING, SO STEP OUT AND BLOCK HIM.
C  (STANDARD TRAVEL ENTRIES CHECK FOR PROP(TROLL)=0.)  SPECIAL STUFF FOR BEAR.

30300 IF(PROP(TROLL).NE.1)GOTO 30310
      CALL PSPEAK(TROLL,1)
      PROP(TROLL)=0
      CALL MOVE(TROLL2,0)
      CALL MOVE(TROLL2+100,0)
      CALL MOVE(TROLL,PLAC(TROLL))
      CALL MOVE(TROLL+100,FIXD(TROLL))
      CALL JUGGLE(CHASM)
      NEWLOC=LOC
      GOTO 2

30310 NEWLOC=PLAC(TROLL)+FIXD(TROLL)-LOC
      IF(PROP(TROLL).EQ.0)PROP(TROLL)=1
      IF(.NOT.TOTING(BEAR))GOTO 2
      CALL RSPEAK(162)
      PROP(CHASM)=1
      PROP(TROLL)=2
      CALL DROP(BEAR,NEWLOC)
      FIXED(BEAR)=-1
      PROP(BEAR)=3
      IF(PROP(SPICES).LT.0)TALLY2=TALLY2+1
      OLDLC2=NEWLOC
      GOTO 99

C  END OF SPECIALS.

C  HANDLE "GO BACK".  LOOK FOR VERB WHICH GOES FROM LOC TO OLDLOC, OR TO OLDLC2
C  IF OLDLOC HAS FORCED-MOTION.  K2 SAVES ENTRY -> FORCED LOC -> PREVIOUS LOC.

20    K=OLDLOC
      IF(FORCED(K))K=OLDLC2
      OLDLC2=OLDLOC
      OLDLOC=LOC
      K2=0
      IF(K.NE.LOC)GOTO 21
      CALL RSPEAK(91)
      GOTO 2

21    LL=MOD((IABS(TRAVEL(KK))/1000),1000)
      IF(LL.EQ.K)GOTO 25
      IF(LL.GT.300)GOTO 22
      J=KEY(LL)
      IF(FORCED(LL).AND.MOD((IABS(TRAVEL(J))/1000),1000).EQ.K)K2=KK
22    IF(TRAVEL(KK).LT.0)GOTO 23
      KK=KK+1
      GOTO 21

23    KK=K2
      IF(KK.NE.0)GOTO 25
      CALL RSPEAK(140)
      GOTO 2

25    K=MOD(IABS(TRAVEL(KK)),1000)
      KK=KEY(LOC)
      GOTO 9

C  LOOK.  CAN'T GIVE MORE DETAIL.  PRETEND IT WASN'T DARK (THOUGH IT MAY "NOW"
C  BE DARK) SO HE WON'T FALL INTO A PIT WHILE STARING INTO THE GLOOM.

30    IF(DETAIL.LT.3)CALL RSPEAK(15)
      DETAIL=DETAIL+1
      WZDARK=.FALSE.
      ABB(LOC)=0
      GOTO 2

C  CAVE.  DIFFERENT MESSAGES DEPENDING ON WHETHER ABOVE GROUND.

40    IF(LOC.LT.8)CALL RSPEAK(57)
      IF(LOC.GE.8)CALL RSPEAK(58)
      GOTO 2

C  NON-APPLICABLE MOTION.  VARIOUS MESSAGES DEPENDING ON WORD GIVEN.

50    SPK=12
      IF(K.GE.43.AND.K.LE.50)SPK=9
      IF(K.EQ.29.OR.K.EQ.30)SPK=9
      IF(K.EQ.7.OR.K.EQ.36.OR.K.EQ.37)SPK=10
      IF(K.EQ.11.OR.K.EQ.19)SPK=11
      IF(VERB.EQ.FIND.OR.VERB.EQ.INVENT)SPK=59
      IF(K.EQ.62.OR.K.EQ.65)SPK=42
      IF(K.EQ.17)SPK=80
      CALL RSPEAK(SPK)
      GOTO 2
      C  "YOU'RE DEAD, JIM."
C
C  IF THE CURRENT LOC IS ZERO, IT MEANS THE CLOWN GOT HIMSELF KILLED.  WE'LL
C  ALLOW THIS MAXDIE TIMES.  MAXDIE IS AUTOMATICALLY SET BASED ON THE NUMBER OF
C  SNIDE MESSAGES AVAILABLE.  EACH DEATH RESULTS IN A MESSAGE (81, 83, ETC.)
C  WHICH OFFERS REINCARNATION; IF ACCEPTED, THIS RESULTS IN MESSAGE 82, 84,
C  ETC.  THE LAST TIME, IF HE WANTS ANOTHER CHANCE, HE GETS A SNIDE REMARK AS
C  WE EXIT.  WHEN REINCARNATED, ALL OBJECTS BEING CARRIED GET DROPPED AT OLDLC2
C  (PRESUMABLY THE LAST PLACE PRIOR TO BEING KILLED) WITHOUT CHANGE OF PROPS.
C  THE LOOP RUNS BACKWARDS TO ASSURE THAT THE BIRD IS DROPPED BEFORE THE CAGE.
C  (THIS KLUGE COULD BE CHANGED ONCE WE'RE SURE ALL REFERENCES TO BIRD AND CAGE
C  ARE DONE BY KEYWORDS.)  THE LAMP IS A SPECIAL CASE (IT WOULDN'T DO TO LEAVE
C  IT IN THE CAVE).  IT IS TURNED OFF AND LEFT OUTSIDE THE BUILDING (ONLY IF HE
C  WAS CARRYING IT, OF COURSE).  HE HIMSELF IS LEFT INSIDE THE BUILDING (AND
C  HEAVEN HELP HIM IF HE TRIES TO XYZZY BACK INTO THE CAVE WITHOUT THE LAMP!).
C  OLDLOC IS ZAPPED SO HE CAN'T JUST "RETREAT".

C  THE EASIEST WAY TO GET KILLED IS TO FALL INTO A PIT IN PITCH DARKNESS.

90    CALL RSPEAK(23)
      OLDLC2=LOC

C  OKAY, HE'S DEAD.  LET'S GET ON WITH IT.

99    IF(CLOSNG)GOTO 95
      YEA=YES(81+NUMDIE*2,82+NUMDIE*2,54)
      NUMDIE=NUMDIE+1
      IF(NUMDIE.EQ.MAXDIE.OR..NOT.YEA)GOTO 20000
      PLACE(WATER)=0
      PLACE(OIL)=0
      IF(TOTING(LAMP))PROP(LAMP)=0
      DO 98 J=1,100
      I=101-J
      IF(.NOT.TOTING(I))GOTO 98
      K=OLDLC2
      IF(I.EQ.LAMP)K=1
      CALL DROP(I,K)
98    CONTINUE
      LOC=3
      OLDLOC=LOC
      GOTO 2000

C  HE DIED DURING CLOSING TIME.  NO RESURRECTION.  TALLY UP A DEATH AND EXIT.

95    CALL RSPEAK(131)
      NUMDIE=NUMDIE+1
      GOTO 20000
      C  ROUTINES FOR PERFORMING THE VARIOUS ACTION VERBS

C  STATEMENT NUMBERS IN THIS SECTION ARE 8000 FOR INTRANSITIVE VERBS, 9000 FOR
C  TRANSITIVE, PLUS TEN TIMES THE VERB NUMBER.  MANY INTRANSITIVE VERBS USE THE
C  TRANSITIVE CODE, AND SOME VERBS USE CODE FOR OTHER VERBS, AS NOTED BELOW.

C  RANDOM INTRANSITIVE VERBS COME HERE.  CLEAR OBJ JUST IN CASE (SEE "ATTACK").

8000  CALL A5TOA1(WD1,WD1X,'What?',TK,K)
      TYPE 8002,(TK(I),I=1,K)
8002  FORMAT(/' ',20A1)
      OBJ=0
      GOTO 2600

C  CARRY, NO OBJECT GIVEN YET.  OK IF ONLY ONE OBJECT PRESENT.

8010  IF(ATLOC(LOC).EQ.0.OR.LINK(ATLOC(LOC)).NE.0)GOTO 8000
      DO 8012 I=1,5
      IF(DLOC(I).EQ.LOC.AND.DFLAG.GE.2)GOTO 8000
8012  CONTINUE
      OBJ=ATLOC(LOC)

C  CARRY AN OBJECT.  SPECIAL CASES FOR BIRD AND CAGE (IF BIRD IN CAGE, CAN'T
C  TAKE ONE WITHOUT THE OTHER.  LIQUIDS ALSO SPECIAL, SINCE THEY DEPEND ON
C  STATUS OF BOTTLE.  ALSO VARIOUS SIDE EFFECTS, ETC.

9010  IF(TOTING(OBJ))GOTO 2011
      SPK=25
      IF(OBJ.EQ.PLANT.AND.PROP(PLANT).LE.0)SPK=115
      IF(OBJ.EQ.BEAR.AND.PROP(BEAR).EQ.1)SPK=169
      IF(OBJ.EQ.CHAIN.AND.PROP(BEAR).NE.0)SPK=170
      IF(FIXED(OBJ).NE.0)GOTO 2011
      IF(OBJ.NE.WATER.AND.OBJ.NE.OIL)GOTO 9017
      IF(HERE(BOTTLE).AND.LIQ(0).EQ.OBJ)GOTO 9018
      OBJ=BOTTLE
      IF(TOTING(BOTTLE).AND.PROP(BOTTLE).EQ.1)GOTO 9220
      IF(PROP(BOTTLE).NE.1)SPK=105
      IF(.NOT.TOTING(BOTTLE))SPK=104
      GOTO 2011
9018  OBJ=BOTTLE
9017  IF(HOLDNG.LT.7)GOTO 9016
      CALL RSPEAK(92)
      GOTO 2012
9016  IF(OBJ.NE.BIRD)GOTO 9014
      IF(PROP(BIRD).NE.0)GOTO 9014
      IF(.NOT.TOTING(ROD))GOTO 9013
      CALL RSPEAK(26)
      GOTO 2012
9013  IF(TOTING(CAGE))GOTO 9015
      CALL RSPEAK(27)
      GOTO 2012
9015  PROP(BIRD)=1
9014  IF((OBJ.EQ.BIRD.OR.OBJ.EQ.CAGE).AND.PROP(BIRD).NE.0)
     1CALL CARRY(BIRD+CAGE-OBJ,LOC)
      CALL CARRY(OBJ,LOC)
      K=LIQ(0)
      IF(OBJ.EQ.BOTTLE.AND.K.NE.0)PLACE(K)=-1
      GOTO 2009

C  DISCARD OBJECT.  "THROW" ALSO COMES HERE FOR MOST OBJECTS.  SPECIAL CASES FOR
C  BIRD (MIGHT ATTACK SNAKE OR DRAGON) AND CAGE (MIGHT CONTAIN BIRD) AND VASE.
C  DROP COINS AT VENDING MACHINE FOR EXTRA BATTERIES.

9020  IF(TOTING(ROD2).AND.OBJ.EQ.ROD.AND..NOT.TOTING(ROD))OBJ=ROD2
      IF(.NOT.TOTING(OBJ))GOTO 2011
      IF(OBJ.NE.BIRD.OR..NOT.HERE(SNAKE))GOTO 9024
      CALL RSPEAK(30)
      IF(CLOSED)GOTO 19000
      CALL DSTROY(SNAKE)
C  SET PROP FOR USE BY TRAVEL OPTIONS
      PROP(SNAKE)=1
9021  K=LIQ(0)
      IF(K.EQ.OBJ)OBJ=BOTTLE
      IF(OBJ.EQ.BOTTLE.AND.K.NE.0)PLACE(K)=0
      IF(OBJ.EQ.CAGE.AND.PROP(BIRD).NE.0)CALL DROP(BIRD,LOC)
      IF(OBJ.EQ.BIRD)PROP(BIRD)=0
      CALL DROP(OBJ,LOC)
      GOTO 2012

9024  IF(OBJ.NE.COINS.OR..NOT.HERE(VEND))GOTO 9025
      CALL DSTROY(COINS)
      CALL DROP(BATTER,LOC)
      CALL PSPEAK(BATTER,0)
      GOTO 2012

9025  IF(OBJ.NE.BIRD.OR..NOT.AT(DRAGON).OR.PROP(DRAGON).NE.0)GOTO 9026
      CALL RSPEAK(154)
      CALL DSTROY(BIRD)
      PROP(BIRD)=0
      IF(PLACE(SNAKE).EQ.PLAC(SNAKE))TALLY2=TALLY2+1
      GOTO 2012

9026  IF(OBJ.NE.BEAR.OR..NOT.AT(TROLL))GOTO 9027
      CALL RSPEAK(163)
      CALL MOVE(TROLL,0)
      CALL MOVE(TROLL+100,0)
      CALL MOVE(TROLL2,PLAC(TROLL))
      CALL MOVE(TROLL2+100,FIXD(TROLL))
      CALL JUGGLE(CHASM)
      PROP(TROLL)=2
      GOTO 9021

9027  IF(OBJ.EQ.VASE.AND.LOC.NE.PLAC(PILLOW))GOTO 9028
      CALL RSPEAK(54)
      GOTO 9021

9028  PROP(VASE)=2
      IF(AT(PILLOW))PROP(VASE)=0
      CALL PSPEAK(VASE,PROP(VASE)+1)
      IF(PROP(VASE).NE.0)FIXED(VASE)=-1
      GOTO 9021

C  SAY.  ECHO WD2 (OR WD1 IF NO WD2 (SAY WHAT?, ETC.).)  MAGIC WORDS OVERRIDE.

9030  CALL A5TOA1(WD2,WD2X,'".',TK,K)
      IF(WD2.EQ.0)CALL A5TOA1(WD1,WD1X,'".',TK,K)
      IF(WD2.NE.0)WD1=WD2
      I=VOCAB(WD1,-1)
      IF(I.EQ.62.OR.I.EQ.65.OR.I.EQ.71.OR.I.EQ.2025)GOTO 9035
      TYPE 9032,(TK(I),I=1,K)
9032  FORMAT(/' Okay, "',20A1)
      GOTO 2012

9035  WD2=0
      OBJ=0
      GOTO 2630

C  LOCK, UNLOCK, NO OBJECT GIVEN.  ASSUME VARIOUS THINGS IF PRESENT.

8040  SPK=28
      IF(HERE(CLAM))OBJ=CLAM
      IF(HERE(OYSTER))OBJ=OYSTER
      IF(AT(DOOR))OBJ=DOOR
      IF(AT(GRATE))OBJ=GRATE
      IF(OBJ.NE.0.AND.HERE(CHAIN))GOTO 8000
      IF(HERE(CHAIN))OBJ=CHAIN
      IF(OBJ.EQ.0)GOTO 2011

C  LOCK, UNLOCK OBJECT.  SPECIAL STUFF FOR OPENING CLAM/OYSTER AND FOR CHAIN.

9040  IF(OBJ.EQ.CLAM.OR.OBJ.EQ.OYSTER)GOTO 9046
      IF(OBJ.EQ.DOOR)SPK=111
      IF(OBJ.EQ.DOOR.AND.PROP(DOOR).EQ.1)SPK=54
      IF(OBJ.EQ.CAGE)SPK=32
      IF(OBJ.EQ.KEYS)SPK=55
      IF(OBJ.EQ.GRATE.OR.OBJ.EQ.CHAIN)SPK=31
      IF(SPK.NE.31.OR..NOT.HERE(KEYS))GOTO 2011
      IF(OBJ.EQ.CHAIN)GOTO 9048
      IF(.NOT.CLOSNG)GOTO 9043
      K=130
      IF(.NOT.PANIC)CLOCK2=15
      PANIC=.TRUE.
      GOTO 2010

9043  K=34+PROP(GRATE)
      PROP(GRATE)=1
      IF(VERB.EQ.LOCK)PROP(GRATE)=0
      K=K+2*PROP(GRATE)
      GOTO 2010

C  CLAM/OYSTER.
9046  K=0
      IF(OBJ.EQ.OYSTER)K=1
      SPK=124+K
      IF(TOTING(OBJ))SPK=120+K
      IF(.NOT.TOTING(TRIDNT))SPK=122+K
      IF(VERB.EQ.LOCK)SPK=61
      IF(SPK.NE.124)GOTO 2011
      CALL DSTROY(CLAM)
      CALL DROP(OYSTER,LOC)
      CALL DROP(PEARL,105)
      GOTO 2011

C  CHAIN.
9048  IF(VERB.EQ.LOCK)GOTO 9049
      SPK=171
      IF(PROP(BEAR).EQ.0)SPK=41
      IF(PROP(CHAIN).EQ.0)SPK=37
      IF(SPK.NE.171)GOTO 2011
      PROP(CHAIN)=0
      FIXED(CHAIN)=0
      IF(PROP(BEAR).NE.3)PROP(BEAR)=2
      FIXED(BEAR)=2-PROP(BEAR)
      GOTO 2011

9049  SPK=172
      IF(PROP(CHAIN).NE.0)SPK=34
      IF(LOC.NE.PLAC(CHAIN))SPK=173
      IF(SPK.NE.172)GOTO 2011
      PROP(CHAIN)=2
      IF(TOTING(CHAIN))CALL DROP(CHAIN,LOC)
      FIXED(CHAIN)=-1
      GOTO 2011

C  LIGHT LAMP

9070  IF(.NOT.HERE(LAMP))GOTO 2011
      SPK=184
      IF(LIMIT.LT.0)GOTO 2011
      PROP(LAMP)=1
      CALL RSPEAK(39)
      IF(WZDARK)GOTO 2000
      GOTO 2012

C  LAMP OFF

9080  IF(.NOT.HERE(LAMP))GOTO 2011
      PROP(LAMP)=0
      CALL RSPEAK(40)
      IF(DARK(0))CALL RSPEAK(16)
      GOTO 2012

C  WAVE.  NO EFFECT UNLESS WAVING ROD AT FISSURE.

9090  IF((.NOT.TOTING(OBJ)).AND.(OBJ.NE.ROD.OR..NOT.TOTING(ROD2)))
     1SPK=29
      IF(OBJ.NE.ROD.OR..NOT.AT(FISSUR).OR..NOT.TOTING(OBJ)
     1.OR.CLOSNG)GOTO 2011
      PROP(FISSUR)=1-PROP(FISSUR)
      CALL PSPEAK(FISSUR,2-PROP(FISSUR))
      GOTO 2012

C  ATTACK.  ASSUME TARGET IF UNAMBIGUOUS.  "THROW" ALSO LINKS HERE.  ATTACKABLE
C  OBJECTS FALL INTO TWO CATEGORIES: ENEMIES (SNAKE, DWARF, ETC.)  AND OTHERS
C  (BIRD, CLAM).  AMBIGUOUS IF TWO ENEMIES, OR IF NO ENEMIES BUT TWO OTHERS.

9120  DO 9121 I=1,5
      IF(DLOC(I).EQ.LOC.AND.DFLAG.GE.2)GOTO 9122
9121  CONTINUE
      I=0
9122  IF(OBJ.NE.0)GOTO 9124
      IF(I.NE.0)OBJ=DWARF
      IF(HERE(SNAKE))OBJ=OBJ*100+SNAKE
      IF(AT(DRAGON).AND.PROP(DRAGON).EQ.0)OBJ=OBJ*100+DRAGON
      IF(AT(TROLL))OBJ=OBJ*100+TROLL
      IF(HERE(BEAR).AND.PROP(BEAR).EQ.0)OBJ=OBJ*100+BEAR
      IF(OBJ.GT.100)GOTO 8000
      IF(OBJ.NE.0)GOTO 9124
C  CAN'T ATTACK BIRD BY THROWING AXE.
      IF(HERE(BIRD).AND.VERB.NE.THROW)OBJ=BIRD
C  CLAM AND OYSTER BOTH TREATED AS CLAM FOR INTRANSITIVE CASE; NO HARM DONE.
      IF(HERE(CLAM).OR.HERE(OYSTER))OBJ=100*OBJ+CLAM
      IF(OBJ.GT.100)GOTO 8000
9124  IF(OBJ.NE.BIRD)GOTO 9125
      SPK=137
      IF(CLOSED)GOTO 2011
      CALL DSTROY(BIRD)
      PROP(BIRD)=0
      IF(PLACE(SNAKE).EQ.PLAC(SNAKE))TALLY2=TALLY2+1
      SPK=45
9125  IF(OBJ.EQ.0)SPK=44
      IF(OBJ.EQ.CLAM.OR.OBJ.EQ.OYSTER)SPK=150
      IF(OBJ.EQ.SNAKE)SPK=46
      IF(OBJ.EQ.DWARF)SPK=49
      IF(OBJ.EQ.DWARF.AND.CLOSED)GOTO 19000
      IF(OBJ.EQ.DRAGON)SPK=167
      IF(OBJ.EQ.TROLL)SPK=157
      IF(OBJ.EQ.BEAR)SPK=165+(PROP(BEAR)+1)/2
      IF(OBJ.NE.DRAGON.OR.PROP(DRAGON).NE.0)GOTO 2011
C  FUN STUFF FOR DRAGON.  IF HE INSISTS ON ATTACKING IT, WIN!  SET PROP TO DEAD,
C  MOVE DRAGON TO CENTRAL LOC (STILL FIXED), MOVE RUG THERE (NOT FIXED), AND
C  MOVE HIM THERE, TOO.  THEN DO A NULL MOTION TO GET NEW DESCRIPTION.
      CALL RSPEAK(49)
      VERB=0
      OBJ=0
      CALL GETIN(WD1,WD1X,WD2,WD2X)
      IF(WD1.NE.'Y'.AND.WD1.NE.'YES')GOTO 2608
      CALL PSPEAK(DRAGON,1)
      PROP(DRAGON)=2
      PROP(RUG)=0
      K=(PLAC(DRAGON)+FIXD(DRAGON))/2
      CALL MOVE(DRAGON+100,-1)
      CALL MOVE(RUG+100,0)
      CALL MOVE(DRAGON,K)
      CALL MOVE(RUG,K)
      DO 9126 OBJ=1,100
      IDONDX=OBJ
      IF(PLACE(IDONDX).EQ.PLAC(DRAGON).OR.
     1PLACE(IDONDX).EQ.FIXD(DRAGON))
     2CALL MOVE(IDONDX,K)
9126  CONTINUE
      LOC=K
      K=NULL
      GOTO 8

C  POUR.  IF NO OBJECT, OR OBJECT IS BOTTLE, ASSUME CONTENTS OF BOTTLE.
C  SPECIAL TESTS FOR POURING WATER OR OIL ON PLANT OR RUSTY DOOR.

9130  IF(OBJ.EQ.BOTTLE.OR.OBJ.EQ.0)OBJ=LIQ(0)
      IF(OBJ.EQ.0)GOTO 8000
      IF(.NOT.TOTING(OBJ))GOTO 2011
      SPK=78
      IF(OBJ.NE.OIL.AND.OBJ.NE.WATER)GOTO 2011
      PROP(BOTTLE)=1
      PLACE(OBJ)=0
      SPK=77
      IF(.NOT.(AT(PLANT).OR.AT(DOOR)))GOTO 2011

      IF(AT(DOOR))GOTO 9132
      SPK=112
      IF(OBJ.NE.WATER)GOTO 2011
      CALL PSPEAK(PLANT,PROP(PLANT)+1)
      PROP(PLANT)=MOD(PROP(PLANT)+2,6)
      PROP(PLANT2)=PROP(PLANT)/2
      K=NULL
      GOTO 8

9132  PROP(DOOR)=0
      IF(OBJ.EQ.OIL)PROP(DOOR)=1
      SPK=113+PROP(DOOR)
      GOTO 2011

C  EAT.  INTRANSITIVE: ASSUME FOOD IF PRESENT, ELSE ASK WHAT.  TRANSITIVE: FOOD
C  OK, SOME THINGS LOSE APPETITE, REST ARE RIDICULOUS.

8140  IF(.NOT.HERE(FOOD))GOTO 8000
8142  CALL DSTROY(FOOD)
      SPK=72
      GOTO 2011

9140  IF(OBJ.EQ.FOOD)GOTO 8142
      IF(OBJ.EQ.BIRD.OR.OBJ.EQ.SNAKE.OR.OBJ.EQ.CLAM.OR.OBJ.EQ.OYSTER
     1.OR.OBJ.EQ.DWARF.OR.OBJ.EQ.DRAGON.OR.OBJ.EQ.TROLL
     2.OR.OBJ.EQ.BEAR)SPK=71
      GOTO 2011

C  DRINK.  IF NO OBJECT, ASSUME WATER AND LOOK FOR IT HERE.  IF WATER IS IN
C  THE BOTTLE, DRINK THAT, ELSE MUST BE AT A WATER LOC, SO DRINK STREAM.

9150  IF(OBJ.EQ.0.AND.LIQLOC(LOC).NE.WATER.AND.(LIQ(0).NE.WATER
     1.OR..NOT.HERE(BOTTLE)))GOTO 8000
      IF(OBJ.NE.0.AND.OBJ.NE.WATER)SPK=110
      IF(SPK.EQ.110.OR.LIQ(0).NE.WATER.OR..NOT.HERE(BOTTLE))GOTO 2011
      PROP(BOTTLE)=1
      PLACE(WATER)=0
      SPK=74
      GOTO 2011

C  RUB.  YIELDS VARIOUS SNIDE REMARKS.

9160  IF(OBJ.NE.LAMP)SPK=76
      GOTO 2011

C  THROW.  SAME AS DISCARD UNLESS AXE.  THEN SAME AS ATTACK EXCEPT IGNORE BIRD,
C  AND IF DWARF IS PRESENT THEN ONE MIGHT BE KILLED.  (ONLY WAY TO DO SO!)
C  AXE ALSO SPECIAL FOR DRAGON, BEAR, AND TROLL.  TREASURES SPECIAL FOR TROLL.

9170  IF(TOTING(ROD2).AND.OBJ.EQ.ROD.AND..NOT.TOTING(ROD))OBJ=ROD2
      IF(.NOT.TOTING(OBJ))GOTO 2011
      IF(OBJ.GE.50.AND.OBJ.LE.MAXTRS.AND.AT(TROLL))GOTO 9178
      IF(OBJ.EQ.FOOD.AND.HERE(BEAR))GOTO 9177
      IF(OBJ.NE.AXE)GOTO 9020
      DO 9171 I=1,5
C  NEEDN'T CHECK DFLAG IF AXE IS HERE.
      IF(DLOC(I).EQ.LOC)GOTO 9172
9171  CONTINUE
      SPK=152
      IF(AT(DRAGON).AND.PROP(DRAGON).EQ.0)GOTO 9175
      SPK=158
      IF(AT(TROLL))GOTO 9175
      IF(HERE(BEAR).AND.PROP(BEAR).EQ.0)GOTO 9176
      OBJ=0
      GOTO 9120

9172  SPK=48
C  IF SAVED NOT = -1, HE BYPASSED THE "START" CALL.
      IF(RAN(3).EQ.0.OR.SAVED.NE.-1)GOTO 9175
      DSEEN(I)=.FALSE.
      DLOC(I)=0
      SPK=47
      DKILL=DKILL+1
      IF(DKILL.EQ.1)SPK=149
9175  CALL RSPEAK(SPK)
      CALL DROP(AXE,LOC)
      K=NULL
      GOTO 8

C  THIS'LL TEACH HIM TO THROW THE AXE AT THE BEAR!
9176  SPK=164
      CALL DROP(AXE,LOC)
      FIXED(AXE)=-1
      PROP(AXE)=1
      CALL JUGGLE(BEAR)
      GOTO 2011

C  BUT THROWING FOOD IS ANOTHER STORY.
9177  OBJ=BEAR
      GOTO 9210

9178  SPK=159
C  SNARF A TREASURE FOR THE TROLL.
      CALL DROP(OBJ,0)
      CALL MOVE(TROLL,0)
      CALL MOVE(TROLL+100,0)
      CALL DROP(TROLL2,PLAC(TROLL))
      CALL DROP(TROLL2+100,FIXD(TROLL))
      CALL JUGGLE(CHASM)
      GOTO 2011

C  QUIT.  INTRANSITIVE ONLY.  VERIFY INTENT AND EXIT IF THAT'S WHAT HE WANTS.

8180  GAVEUP=YES(22,54,54)
8185  IF(GAVEUP)GOTO 20000
      GOTO 2012

C  FIND.  MIGHT BE CARRYING IT, OR IT MIGHT BE HERE.  ELSE GIVE CAVEAT.

9190  IF(AT(OBJ).OR.(LIQ(0).EQ.OBJ.AND.AT(BOTTLE))
     1.OR.K.EQ.LIQLOC(LOC))SPK=94
      DO 9192 I=1,5
9192  IF(DLOC(I).EQ.LOC.AND.DFLAG.GE.2.AND.OBJ.EQ.DWARF)SPK=94
      IF(CLOSED)SPK=138
      IF(TOTING(OBJ))SPK=24
      GOTO 2011

C  INVENTORY.  IF OBJECT, TREAT SAME AS FIND.  ELSE REPORT ON CURRENT BURDEN.

8200  SPK=98
      DO 8201 I=1,100
      IDONDX=I
      IF(IDONDX.EQ.BEAR.OR..NOT.TOTING(IDONDX))GOTO 8201
      IF(SPK.EQ.98)CALL RSPEAK(99)
      BLKLIN=.FALSE.
      CALL PSPEAK(IDONDX,-1)
      BLKLIN=.TRUE.
      SPK=0
8201  CONTINUE
      IF(TOTING(BEAR))SPK=141
      GOTO 2011

C  FEED.  IF BIRD, NO SEED.  SNAKE, DRAGON, TROLL: QUIP.  IF DWARF, MAKE HIM
C  MAD.  BEAR, SPECIAL.

9210  IF(OBJ.NE.BIRD)GOTO 9212
      SPK=100
      GOTO 2011

9212  IF(OBJ.NE.SNAKE.AND.OBJ.NE.DRAGON.AND.OBJ.NE.TROLL)GOTO 9213
      SPK=102
      IF(OBJ.EQ.DRAGON.AND.PROP(DRAGON).NE.0)SPK=110
      IF(OBJ.EQ.TROLL)SPK=182
      IF(OBJ.NE.SNAKE.OR.CLOSED.OR..NOT.HERE(BIRD))GOTO 2011
      SPK=101
      CALL DSTROY(BIRD)
      PROP(BIRD)=0
      TALLY2=TALLY2+1
      GOTO 2011

9213  IF(OBJ.NE.DWARF)GOTO 9214
      IF(.NOT.HERE(FOOD))GOTO 2011
      SPK=103
      DFLAG=DFLAG+1
      GOTO 2011

9214  IF(OBJ.NE.BEAR)GOTO 9215
      IF(PROP(BEAR).EQ.0)SPK=102
      IF(PROP(BEAR).EQ.3)SPK=110
      IF(.NOT.HERE(FOOD))GOTO 2011
      CALL DSTROY(FOOD)
      PROP(BEAR)=1
      FIXED(AXE)=0
      PROP(AXE)=0
      SPK=168
      GOTO 2011

9215  SPK=14
      GOTO 2011

C  FILL.  BOTTLE MUST BE EMPTY, AND SOME LIQUID AVAILABLE.  (VASE IS NASTY.)

9220  IF(OBJ.EQ.VASE)GOTO 9222
      IF(OBJ.NE.0.AND.OBJ.NE.BOTTLE)GOTO 2011
      IF(OBJ.EQ.0.AND..NOT.HERE(BOTTLE))GOTO 8000
      SPK=107
      IF(LIQLOC(LOC).EQ.0)SPK=106
      IF(LIQ(0).NE.0)SPK=105
      IF(SPK.NE.107)GOTO 2011
      PROP(BOTTLE)=MOD(COND(LOC),4)/2*2
      K=LIQ(0)
      IF(TOTING(BOTTLE))PLACE(K)=-1
      IF(K.EQ.OIL)SPK=108
      GOTO 2011

9222  SPK=29
      IF(LIQLOC(LOC).EQ.0)SPK=144
      IF(LIQLOC(LOC).EQ.0.OR..NOT.TOTING(VASE))GOTO 2011
      CALL RSPEAK(145)
      PROP(VASE)=2
      FIXED(VASE)=-1
      GOTO 9024

C  BLAST.  NO EFFECT UNLESS YOU'VE GOT DYNAMITE, WHICH IS A NEAT TRICK!

9230  IF(PROP(ROD2).LT.0.OR..NOT.CLOSED)GOTO 2011
      BONUS=133
      IF(LOC.EQ.115)BONUS=134
      IF(HERE(ROD2))BONUS=135
      CALL RSPEAK(BONUS)
      GOTO 20000

C  SCORE.  GO TO SCORING SECTION, WHICH WILL RETURN TO 8241 IF SCORNG IS TRUE.

8240  SCORNG=.TRUE.
      GOTO 20000

8241  SCORNG=.FALSE.
      TYPE 8243,SCORE,MXSCOR
8243  FORMAT(/' If you were to quit now, you would score',I4
     1,' out of a possible',I4,'.')
      GAVEUP=YES(143,54,54)
      GOTO 8185

C  FEE FIE FOE FOO (AND FUM).  ADVANCE TO NEXT STATE IF GIVEN IN PROPER ORDER.
C  LOOK UP WD1 IN SECTION 3 OF VOCAB TO DETERMINE WHICH WORD WE'VE GOT.  LAST
C  WORD ZIPS THE EGGS BACK TO THE GIANT ROOM (UNLESS ALREADY THERE).

8250  K=VOCAB(WD1,3)
      SPK=42
      IF(FOOBAR.EQ.1-K)GOTO 8252
      IF(FOOBAR.NE.0)SPK=151
      GOTO 2011

8252  FOOBAR=K
      IF(K.NE.4)GOTO 2009
      FOOBAR=0
      IF(PLACE(EGGS).EQ.PLAC(EGGS)
     1.OR.(TOTING(EGGS).AND.LOC.EQ.PLAC(EGGS)))GOTO 2011
C  BRING BACK TROLL IF WE STEAL THE EGGS BACK FROM HIM BEFORE CROSSING.
      IF(PLACE(EGGS).EQ.0.AND.PLACE(TROLL).EQ.0.AND.PROP(TROLL).EQ.0)
     1PROP(TROLL)=1
      K=2
      IF(HERE(EGGS))K=1
      IF(LOC.EQ.PLAC(EGGS))K=0
      CALL MOVE(EGGS,PLAC(EGGS))
      CALL PSPEAK(EGGS,K)
      GOTO 2012

C  BRIEF.  INTRANSITIVE ONLY.  SUPPRESS LONG DESCRIPTIONS AFTER FIRST TIME.

8260  SPK=156
      ABBNUM=10000
      DETAIL=3
      GOTO 2011

C  READ.  MAGAZINES IN DWARVISH, MESSAGE WE'VE SEEN, AND . . . OYSTER?

8270  IF(HERE(MAGZIN))OBJ=MAGZIN
      IF(HERE(TABLET))OBJ=OBJ*100+TABLET
      IF(HERE(MESSAG))OBJ=OBJ*100+MESSAG
      IF(CLOSED.AND.TOTING(OYSTER))OBJ=OYSTER
      IF(OBJ.GT.100.OR.OBJ.EQ.0.OR.DARK(0))GOTO 8000

9270  IF(DARK(0))GOTO 5190
      IF(OBJ.EQ.MAGZIN)SPK=190
      IF(OBJ.EQ.TABLET)SPK=196
      IF(OBJ.EQ.MESSAG)SPK=191
      IF(OBJ.EQ.OYSTER.AND.HINTED(2).AND.TOTING(OYSTER))SPK=194
      IF(OBJ.NE.OYSTER.OR.HINTED(2).OR..NOT.TOTING(OYSTER)
     1.OR..NOT.CLOSED)GOTO 2011
      HINTED(2)=YES(192,193,54)
      GOTO 2012

C  BREAK.  ONLY WORKS FOR MIRROR IN REPOSITORY AND, OF COURSE, THE VASE.

9280  IF(OBJ.EQ.MIRROR)SPK=148
      IF(OBJ.EQ.VASE.AND.PROP(VASE).EQ.0)GOTO 9282
      IF(OBJ.NE.MIRROR.OR..NOT.CLOSED)GOTO 2011
      CALL RSPEAK(197)
      GOTO 19000

9282  SPK=198
      IF(TOTING(VASE))CALL DROP(VASE,LOC)
      PROP(VASE)=2
      FIXED(VASE)=-1
      GOTO 2011

C  WAKE.  ONLY USE IS TO DISTURB THE DWARVES.

9290  IF(OBJ.NE.DWARF.OR..NOT.CLOSED)GOTO 2011
      CALL RSPEAK(199)
      GOTO 19000

C  SUSPEND.  OFFER TO EXIT LEAVING THINGS RESTARTABLE, BUT REQUIRING A DELAY
C  BEFORE RESTARTING (SO CAN'T SAVE THE WORLD BEFORE TRYING SOMETHING RISKY).
C  UPON RESTARTING, SETUP=-1 CAUSES RETURN TO 8305 TO PICK UP AGAIN.

8300  SPK=201
      IF(DEMO)GOTO 2011
      TYPE 8302,LATNCY
8302  FORMAT(/' I can suspend your adventure for you so that you can',
     1' resume later, but'/' you will have to wait at least',
     2I3,' minutes before continuing.')
      IF(.NOT.YES(200,54,54))GOTO 2012
      CALL DATIME(SAVED,SAVET)
      SETUP=-1
      CALL CIAO

8305  YEA=START(0)
      SETUP=3
      K=NULL
      GOTO 8

C  HOURS.  REPORT CURRENT NON-PRIME-TIME HOURS.

8310  CALL MSPEAK(6)
      CALL HOURS
      GOTO 2012
      C  HINTS

C  COME HERE IF HE'S BEEN LONG ENOUGH AT REQUIRED LOC(S) FOR SOME UNUSED HINT.
C  HINT NUMBER IS IN VARIABLE "HINT".  BRANCH TO QUICK TEST FOR ADDITIONAL
C  CONDITIONS, THEN COME BACK TO DO NEAT STUFF.  GOTO 40010 IF CONDITIONS ARE
C  MET AND WE WANT TO OFFER THE HINT.  GOTO 40020 TO CLEAR HINTLC BACK TO ZERO,
C  40030 TO TAKE NO ACTION YET.

40000 GOTO (40400,40500,40600,40700,40800,40900)(HINT-3)
C	      CAVE  BIRD  SNAKE MAZE  DARK  WITT
      CALL BUG(27)

40010 HINTLC(HINT)=0
      IF(.NOT.YES(HINTS(HINT,3),0,54))GOTO 2602
      TYPE 40012,HINTS(HINT,2)
40012 FORMAT(/' I am prepared to give you a hint, but it will cost you',
     1I2,' points.')
      HINTED(HINT)=YES(175,HINTS(HINT,4),54)
      IF(HINTED(HINT).AND.LIMIT.GT.30)LIMIT=LIMIT+30*HINTS(HINT,2)
40020 HINTLC(HINT)=0
40030 GOTO 2602

C  NOW FOR THE QUICK TESTS.  SEE DATABASE DESCRIPTION FOR ONE-LINE NOTES.

40400 IF(PROP(GRATE).EQ.0.AND..NOT.HERE(KEYS))GOTO 40010
      GOTO 40020

40500 IF(HERE(BIRD).AND.TOTING(ROD).AND.OBJ.EQ.BIRD)GOTO 40010
      GOTO 40030

40600 IF(HERE(SNAKE).AND..NOT.HERE(BIRD))GOTO 40010
      GOTO 40020

40700 IF(ATLOC(LOC).EQ.0.AND.ATLOC(OLDLOC).EQ.0
     1.AND.ATLOC(OLDLC2).EQ.0.AND.HOLDNG.GT.1)GOTO 40010
      GOTO 40020

40800 IF(PROP(EMRALD).NE.-1.AND.PROP(PYRAM).EQ.-1)GOTO 40010
      GOTO 40020

40900 GOTO 40010
      C  CAVE CLOSING AND SCORING


C  THESE SECTIONS HANDLE THE CLOSING OF THE CAVE.  THE CAVE CLOSES "CLOCK1"
C  TURNS AFTER THE LAST TREASURE HAS BEEN LOCATED (INCLUDING THE PIRATE'S
C  CHEST, WHICH MAY OF COURSE NEVER SHOW UP).  NOTE THAT THE TREASURES NEED NOT
C  HAVE BEEN TAKEN YET, JUST LOCATED.  HENCE CLOCK1 MUST BE LARGE ENOUGH TO GET
C  OUT OF THE CAVE (IT ONLY TICKS WHILE INSIDE THE CAVE).  WHEN IT HITS ZERO,
C  WE BRANCH TO 10000 TO START CLOSING THE CAVE, AND THEN SIT BACK AND WAIT FOR
C  HIM TO TRY TO GET OUT.  IF HE DOESN'T WITHIN CLOCK2 TURNS, WE CLOSE THE
C  CAVE; IF HE DOES TRY, WE ASSUME HE PANICS, AND GIVE HIM A FEW ADDITIONAL
C  TURNS TO GET FRANTIC BEFORE WE CLOSE.  WHEN CLOCK2 HITS ZERO, WE BRANCH TO
C  11000 TO TRANSPORT HIM INTO THE FINAL PUZZLE.  NOTE THAT THE PUZZLE DEPENDS
C  UPON ALL SORTS OF RANDOM THINGS.  FOR INSTANCE, THERE MUST BE NO WATER OR
C  OIL, SINCE THERE ARE BEANSTALKS WHICH WE DON'T WANT TO BE ABLE TO WATER,
C  SINCE THE CODE CAN'T HANDLE IT.  ALSO, WE CAN HAVE NO KEYS, SINCE THERE IS A
C  GRATE (HAVING MOVED THE FIXED OBJECT!) THERE SEPARATING HIM FROM ALL THE
C  TREASURES.  MOST OF THESE PROBLEMS ARISE FROM THE USE OF NEGATIVE PROP
C  NUMBERS TO SUPPRESS THE OBJECT DESCRIPTIONS UNTIL HE'S ACTUALLY MOVED THE
C  OBJECTS.

C  WHEN THE FIRST WARNING COMES, WE LOCK THE GRATE, DESTROY THE BRIDGE, KILL
C  ALL THE DWARVES (AND THE PIRATE), REMOVE THE TROLL AND BEAR (UNLESS DEAD),
C  AND SET "CLOSNG" TO TRUE.  LEAVE THE DRAGON; TOO MUCH TROUBLE TO MOVE IT.
C  FROM NOW UNTIL CLOCK2 RUNS OUT, HE CANNOT UNLOCK THE GRATE, MOVE TO ANY
C  LOCATION OUTSIDE THE CAVE (LOC<9), OR CREATE THE BRIDGE.  NOR CAN HE BE
C  RESURRECTED IF HE DIES.  NOTE THAT THE SNAKE IS ALREADY GONE, SINCE HE GOT
C  TO THE TREASURE ACCESSIBLE ONLY VIA THE HALL OF THE MT. KING.  ALSO, HE'S
C  BEEN IN GIANT ROOM (TO GET EGGS), SO WE CAN REFER TO IT.  ALSO ALSO, HE'S
C  GOTTEN THE PEARL, SO WE KNOW THE BIVALVE IS AN OYSTER.  *AND*, THE DWARVES
C  MUST HAVE BEEN ACTIVATED, SINCE WE'VE FOUND CHEST.

10000 PROP(GRATE)=0
      PROP(FISSUR)=0
      DO 10010 I=1,6
      DSEEN(I)=.FALSE.
10010 DLOC(I)=0
      CALL MOVE(TROLL,0)
      CALL MOVE(TROLL+100,0)
      CALL MOVE(TROLL2,PLAC(TROLL))
      CALL MOVE(TROLL2+100,FIXD(TROLL))
      CALL JUGGLE(CHASM)
      IF(PROP(BEAR).NE.3)CALL DSTROY(BEAR)
      PROP(CHAIN)=0
      FIXED(CHAIN)=0
      PROP(AXE)=0
      FIXED(AXE)=0
      CALL RSPEAK(129)
      CLOCK1=-1
      CLOSNG=.TRUE.
      GOTO 19999

C  ONCE HE'S PANICKED, AND CLOCK2 HAS RUN OUT, WE COME HERE TO SET UP THE
C  STORAGE ROOM.  THE ROOM HAS TWO LOCS, HARDWIRED AS 115 (NE) AND 116 (SW).
C  AT THE NE END, WE PLACE EMPTY BOTTLES, A NURSERY OF PLANTS, A BED OF
C  OYSTERS, A PILE OF LAMPS, RODS WITH STARS, SLEEPING DWARVES, AND HIM.  AND
C  THE SW END WE PLACE GRATE OVER TREASURES, SNAKE PIT, COVEY OF CAGED BIRDS,
C  MORE RODS, AND PILLOWS.  A MIRROR STRETCHES ACROSS ONE WALL.  MANY OF THE
C  OBJECTS COME FROM KNOWN LOCATIONS AND/OR STATES (E.G. THE SNAKE IS KNOWN TO
C  HAVE BEEN DESTROYED AND NEEDN'T BE CARRIED AWAY FROM ITS OLD "PLACE"),
C  MAKING THE VARIOUS OBJECTS BE HANDLED DIFFERENTLY.  WE ALSO DROP ALL OTHER
C  OBJECTS HE MIGHT BE CARRYING (LEST HE HAVE SOME WHICH COULD CAUSE TROUBLE,
C  SUCH AS THE KEYS).  WE DESCRIBE THE FLASH OF LIGHT AND TRUNDLE BACK.

11000 PROP(BOTTLE)=PUT(BOTTLE,115,1)
      PROP(PLANT)=PUT(PLANT,115,0)
      PROP(OYSTER)=PUT(OYSTER,115,0)
      PROP(LAMP)=PUT(LAMP,115,0)
      PROP(ROD)=PUT(ROD,115,0)
      PROP(DWARF)=PUT(DWARF,115,0)
      LOC=115
      OLDLOC=115
      NEWLOC=115

C  LEAVE THE GRATE WITH NORMAL (NON-NEGATIVE PROPERTY).

      FOO=PUT(GRATE,116,0)
      PROP(SNAKE)=PUT(SNAKE,116,1)
      PROP(BIRD)=PUT(BIRD,116,1)
      PROP(CAGE)=PUT(CAGE,116,0)
      PROP(ROD2)=PUT(ROD2,116,0)
      PROP(PILLOW)=PUT(PILLOW,116,0)

      PROP(MIRROR)=PUT(MIRROR,115,0)
      FIXED(MIRROR)=116

      DO 11010 I=1,100
      IDONDX=I
11010 IF(TOTING(IDONDX))CALL DSTROY(IDONDX)

      CALL RSPEAK(132)
      CLOSED=.TRUE.
      GOTO 2

C  ANOTHER WAY WE CAN FORCE AN END TO THINGS IS BY HAVING THE LAMP GIVE OUT.
C  WHEN IT GETS CLOSE, WE COME HERE TO WARN HIM.  WE GO TO 12000 IF THE LAMP
C  AND FRESH BATTERIES ARE HERE, IN WHICH CASE WE REPLACE THE BATTERIES AND
C  CONTINUE.  12200 IS FOR OTHER CASES OF LAMP DYING.  12400 IS WHEN IT GOES
C  OUT, AND 12600 IS IF HE'S WANDERED OUTSIDE AND THE LAMP IS USED UP, IN WHICH
C  CASE WE FORCE HIM TO GIVE UP.

12000 CALL RSPEAK(188)
      PROP(BATTER)=1
      IF(TOTING(BATTER))CALL DROP(BATTER,LOC)
      LIMIT=LIMIT+2500
      LMWARN=.FALSE.
      GOTO 19999

12200 IF(LMWARN.OR..NOT.HERE(LAMP))GOTO 19999
      LMWARN=.TRUE.
      SPK=187
      IF(PLACE(BATTER).EQ.0)SPK=183
      IF(PROP(BATTER).EQ.1)SPK=189
      CALL RSPEAK(SPK)
      GOTO 19999

12400 LIMIT=-1
      PROP(LAMP)=0
      IF(HERE(LAMP))CALL RSPEAK(184)
      GOTO 19999

12600 CALL RSPEAK(185)
      GAVEUP=.TRUE.
      GOTO 20000

C  AND, OF COURSE, DEMO GAMES ARE ENDED BY THE WIZARD.

13000 CALL MSPEAK(1)
      GOTO 20000

C  OH DEAR, HE'S DISTURBED THE DWARVES.

19000 CALL RSPEAK(136)

C  EXIT CODE.  WILL EVENTUALLY INCLUDE SCORING.  FOR NOW, HOWEVER, ...

C  THE PRESENT SCORING ALGORITHM IS AS FOLLOWS:
C     OBJECTIVE:          POINTS:        PRESENT TOTAL POSSIBLE:
C  GETTING WELL INTO CAVE   25                    25
C  EACH TREASURE < CHEST    12                    60
C  TREASURE CHEST ITSELF    14                    14
C  EACH TREASURE > CHEST    16                   144
C  SURVIVING             (MAX-NUM)*10             30
C  NOT QUITTING              4                     4
C  REACHING "CLOSNG"        25                    25
C  "CLOSED": QUIT/KILLED    10
C            KLUTZED        25
C            WRONG WAY      30
C            SUCCESS        45                    45
C  CAME TO WITT'S END        1                     1
C  ROUND OUT THE TOTAL       2                     2
C                                       TOTAL:   350
C  (POINTS CAN ALSO BE DEDUCTED FOR USING HINTS.)

20000 SCORE=0
      MXSCOR=0

C  FIRST TALLY UP THE TREASURES.  MUST BE IN BUILDING AND NOT BROKEN.
C  GIVE THE POOR GUY 2 POINTS JUST FOR FINDING EACH TREASURE.

      DO 20010 I=50,MAXTRS
      IF(PTEXT(I).EQ.0)GOTO 20010
      K=12
      IF(I.EQ.CHEST)K=14
      IF(I.GT.CHEST)K=16
      IF(PROP(I).GE.0)SCORE=SCORE+2
      IF(PLACE(I).EQ.3.AND.PROP(I).EQ.0)SCORE=SCORE+K-2
      MXSCOR=MXSCOR+K
20010 CONTINUE

C  NOW LOOK AT HOW HE FINISHED AND HOW FAR HE GOT.  MAXDIE AND NUMDIE TELL US
C  HOW WELL HE SURVIVED.  GAVEUP SAYS WHETHER HE EXITED VIA QUIT.  DFLAG WILL
C  TELL US IF HE EVER GOT SUITABLY DEEP INTO THE CAVE.  CLOSNG STILL INDICATES
C  WHETHER HE REACHED THE ENDGAME.  AND IF HE GOT AS FAR AS "CAVE CLOSED"
C  (INDICATED BY "CLOSED"), THEN BONUS IS ZERO FOR MUNDANE EXITS OR 133, 134,
C  135 IF HE BLEW IT (SO TO SPEAK).

      SCORE=SCORE+(MAXDIE-NUMDIE)*10
      MXSCOR=MXSCOR+MAXDIE*10
      IF(.NOT.(SCORNG.OR.GAVEUP))SCORE=SCORE+4
      MXSCOR=MXSCOR+4
      IF(DFLAG.NE.0)SCORE=SCORE+25
      MXSCOR=MXSCOR+25
      IF(CLOSNG)SCORE=SCORE+25
      MXSCOR=MXSCOR+25
      IF(.NOT.CLOSED)GOTO 20020
      IF(BONUS.EQ.0)SCORE=SCORE+10
      IF(BONUS.EQ.135)SCORE=SCORE+25
      IF(BONUS.EQ.134)SCORE=SCORE+30
      IF(BONUS.EQ.133)SCORE=SCORE+45
20020 MXSCOR=MXSCOR+45

C  DID HE COME TO WITT'S END AS HE SHOULD?

      IF(PLACE(MAGZIN).EQ.108)SCORE=SCORE+1
      MXSCOR=MXSCOR+1

C  ROUND IT OFF.

      SCORE=SCORE+2
      MXSCOR=MXSCOR+2

C  DEDUCT POINTS FOR HINTS.  HINTS < 4 ARE SPECIAL; SEE DATABASE DESCRIPTION.

      DO 20030 I=1,HNTMAX
20030 IF(HINTED(I))SCORE=SCORE-HINTS(I,2)

C  RETURN TO SCORE COMMAND IF THAT'S WHERE WE CAME FROM.

      IF(SCORNG)GOTO 8241

C  THAT SHOULD BE GOOD ENOUGH.  LET'S TELL HIM ALL ABOUT IT.

      TYPE 20100,SCORE,MXSCOR,TURNS
20100 FORMAT(///' You scored',I4,' out of a possible',I4,
     1', using',I5,' turns.')

      DO 20200 I=1,CLSSES
      IF(CVAL(I).GE.SCORE)GOTO 20210
20200 CONTINUE
      TYPE 20202
20202 FORMAT(/' You just went off my scale!!'/)
      GOTO 25000

20210 CALL SPEAK(CTEXT(I))
      IF(I.EQ.CLSSES-1)GOTO 20220
      K=CVAL(I)+1-SCORE
      KK='s.'
      IF(K.EQ.1)KK='. '
      TYPE 20212,K,KK
20212 FORMAT(/' To achieve the next higher rating, you need',I3,
     1' more point',A2/)
      GOTO 25000

20220 TYPE 20222
20222 FORMAT(/' To achieve the next higher rating ',
     1'would be a neat trick!'//' Congratulations!!'/)

25000 STOP


      END
C  I/O ROUTINES (SPEAK, PSPEAK, RSPEAK, GETIN, YES, A5TOA1)


      SUBROUTINE SPEAK(N)

C  PRINT THE MESSAGE WHICH STARTS AT LINES(N).  PRECEDE IT WITH A BLANK LINE
C  UNLESS BLKLIN IS FALSE.

      IMPLICIT INTEGER(A-Z)
      LOGICAL BLKLIN
      COMMON /TXTCOM/ RTEXT,LINES
      COMMON /BLKCOM/ BLKLIN
      DIMENSION RTEXT(205),LINES(9650)

      IF(N.EQ.0)RETURN
      IF(LINES(N+1).EQ.'>$<')RETURN
      IF(BLKLIN)TYPE 2
      K=N
1     L=IABS(LINES(K))-1
      K=K+1
      TYPE 2,(LINES(I),I=K,L)
2     FORMAT(' ',14A5)
      K=L+1
      IF(LINES(K).GE.0)GOTO 1
      RETURN
      END



      SUBROUTINE PSPEAK(MSG,SKIP)

C  FIND THE SKIP+1ST MESSAGE FROM MSG AND PRINT IT.  MSG SHOULD BE THE INDEX OF
C  THE INVENTORY MESSAGE FOR OBJECT.  (INVEN+N+1 MESSAGE IS PROP=N MESSAGE).

      IMPLICIT INTEGER(A-Z)
      COMMON /TXTCOM/ RTEXT,LINES
      COMMON /PTXCOM/ PTEXT
      DIMENSION RTEXT(205),LINES(9650),PTEXT(100)

      M=PTEXT(MSG)
      IF(SKIP.LT.0)GOTO 9
      DO 3 I=0,SKIP
1     M=IABS(LINES(M))
      IF(LINES(M).GE.0)GOTO 1
3     CONTINUE
9     CALL SPEAK(M)
      RETURN
      END



      SUBROUTINE RSPEAK(I)

C  PRINT THE I-TH "RANDOM" MESSAGE (SECTION 6 OF DATABASE).

      IMPLICIT INTEGER(A-Z)
      COMMON /TXTCOM/ RTEXT
      DIMENSION RTEXT(205)

      IF(I.NE.0)CALL SPEAK(RTEXT(I))
      RETURN
      END



      SUBROUTINE MSPEAK(I)

C  PRINT THE I-TH "MAGIC" MESSAGE (SECTION 12 OF DATABASE).

      IMPLICIT INTEGER(A-Z)
      COMMON /MTXCOM/ MTEXT
      DIMENSION MTEXT(35)

      IF(I.NE.0)CALL SPEAK(MTEXT(I))
      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 6 THRU 10 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 6 THRU 10 IN WORD2X), ELSE WORD2 IS SET TO ZERO.

      IMPLICIT INTEGER(A-Z)
      LOGICAL BLKLIN
      COMMON /BLKCOM/ BLKLIN
      DIMENSION A(5),MASKS(6)
      DATA MASKS/"4000000000,"20000000,"100000,"400,"2,0/
     1,BLANKS/'     '/

      IF(BLKLIN)TYPE 1
1     FORMAT()
2     ACCEPT 3,(A(I),I=1,4)
3     FORMAT(4A5)
      J=0
      DO 9 I=1,4
      IF(A(I).NE.BLANKS)J=1
9     A(I)=A(I).AND.(SHIFT((A(I).AND.'@@@@@'),-1).XOR.-1)
      IF(BLKLIN.AND.J.EQ.0)GOTO 2

      SECOND=0
      WORD1=A(1)
      WORD1X=A(2)
      WORD2=0

      DO 10 J=1,4
      DO 10 K=1,5
      MSK="774000000000
      IF(K.NE.1)MSK="177*MASKS(K)
      IF(((A(J).XOR.BLANKS).AND.MSK).EQ.0)GOTO 15
      IF(SECOND.EQ.0)GOTO 10
      MSK=-MASKS(6-K)
      WORD2=(SHIFT(A(J),7*(K-1)).AND.MSK)
     1+(SHIFT(A(J+1),7*(K-6)).AND.(-2-MSK))
      WORD2X=(SHIFT(A(J+1),7*(K-1)).AND.MSK)
     1+(SHIFT(A(J+2),7*(K-6)).AND.(-2-MSK))
      RETURN

15    IF(SECOND.EQ.1)GOTO 10
      SECOND=1
      IF(J.EQ.1)WORD1=(WORD1.AND.-MASKS(K))
     1.OR.(BLANKS.AND.(-MASKS(K).XOR.-1))
10    CONTINUE
      RETURN
      END



      LOGICAL FUNCTION YES(X,Y,Z)

C  CALL YESX (BELOW) WITH MESSAGES FROM SECTION 6.

      IMPLICIT INTEGER(A-Z)
      EXTERNAL RSPEAK
      LOGICAL YESX

      YES=YESX(X,Y,Z,RSPEAK)
      RETURN
      END



      LOGICAL FUNCTION YESM(X,Y,Z)

C  CALL YESX (BELOW) WITH MESSAGES FROM SECTION 12.

      IMPLICIT INTEGER(A-Z)
      EXTERNAL MSPEAK
      LOGICAL YESX

      YESM=YESX(X,Y,Z,MSPEAK)
      RETURN
      END



      LOGICAL FUNCTION YESX(X,Y,Z,SPK)

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.  SPK IS EITHER RSPEAK OR MSPEAK.

      IMPLICIT INTEGER(A-Z)

1     IF(X.NE.0)CALL SPK(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    YESX=.TRUE.
      IF(Y.NE.0)CALL SPK(Y)
      RETURN
20    YESX=.FALSE.
      IF(Z.NE.0)CALL SPK(Z)
      RETURN
      END



      SUBROUTINE A5TOA1(A,B,C,CHARS,LENG)

C  A AND B CONTAIN A 1- TO 9-CHARACTER WORD IN A5 FORMAT, C CONTAINS ANOTHER
C  WORD AND/OR PUNCTUATION.  THEY ARE UNPACKED TO ONE CHARACTER PER WORD IN THE
C  ARRAY "CHARS", WITH EXACTLY ONE BLANK BETWEEN B AND C (OR NONE, IF C >= 0).
C  THE INDEX OF THE LAST NON-BLANK CHAR IN CHARS IS RETURNED IN LENG.

      IMPLICIT INTEGER(A-Z)
      DIMENSION CHARS(20),WORDS(3)
      DATA MASK,BLANK/"774000000000,' '/

      WORDS(1)=A
      WORDS(2)=B
      WORDS(3)=C
      POSN=1
      DO 1 WORD=1,3
      IF(WORD.EQ.2.AND.POSN.NE.6)GOTO 1
      IF(WORD.EQ.3.AND.C.LT.0)POSN=POSN+1
      DO 2 CH=1,5
      CHARS(POSN)=(WORDS(WORD).AND.MASK)+(BLANK-(BLANK.AND.MASK))
      IF(CHARS(POSN).EQ.BLANK)GOTO 1
      LENG=POSN
      WORDS(WORD)=SHIFT(WORDS(WORD),7)
2     POSN=POSN+1
1     CONTINUE
      RETURN
      END
      C  DATA STRUCTURE ROUTINES (VOCAB, DSTROY, JUGGLE, MOVE, PUT, CARRY, DROP)


      INTEGER 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)
      COMMON /VOCCOM/ KTAB,ATAB,TABSIZ
      DIMENSION KTAB(300),ATAB(300)

      HASH=ID.XOR.'PHROG'
      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
      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)

      CALL MOVE(OBJECT,0)
      RETURN
      END



      SUBROUTINE 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.

      IMPLICIT INTEGER(A-Z)
      COMMON /PLACOM/ ATLOC,LINK,PLACE,FIXED,HOLDNG
      DIMENSION ATLOC(150),LINK(200),PLACE(100),FIXED(100)

      I=PLACE(OBJECT)
      J=FIXED(OBJECT)
      CALL MOVE(OBJECT,I)
      CALL MOVE(OBJECT+100,J)
      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,LINK,PLACE,FIXED,HOLDNG
      DIMENSION ATLOC(150),LINK(200),PLACE(100),FIXED(100)

      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



      SUBROUTINE 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.

      IMPLICIT INTEGER(A-Z)
      COMMON /PLACOM/ ATLOC,LINK,PLACE,FIXED,HOLDNG
      DIMENSION ATLOC(150),LINK(200),PLACE(100),FIXED(100)

      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
      END



      SUBROUTINE 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.

      IMPLICIT INTEGER(A-Z)
      COMMON /PLACOM/ ATLOC,LINK,PLACE,FIXED,HOLDNG
      DIMENSION ATLOC(150),LINK(200),PLACE(100),FIXED(100)

      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
      C  WIZARDRY ROUTINES (START, MAINT, WIZARD, HOURS(X), NEWHRS(X), MOTD, POOF)


      LOGICAL FUNCTION START(DUMMY)

C  CHECK TO SEE IF THIS IS "PRIME TIME".  IF SO, ONLY WIZARDS MAY PLAY, THOUGH
C  OTHERS MAY BE ALLOWED A SHORT GAME FOR DEMONSTRATION PURPOSES.  IF SETUP<0,
C  WE'RE CONTINUING FROM A SAVED GAME, SO CHECK FOR SUITABLE LATENCY.  RETURN
C  TRUE IF THIS IS A DEMO GAME (VALUE IS IGNORED FOR RESTARTS).

      IMPLICIT INTEGER(A-Z)
      LOGICAL PTIME,SOON,YESM
      DIMENSION HNAME(4)
      COMMON /WIZCOM/ WKDAY,WKEND,HOLID,HBEGIN,HEND,HNAME,
     1SHORT,MAGIC,MAGNM,LATNCY,SAVED,SAVET,SETUP

C  FIRST FIND OUT WHETHER IT IS PRIME TIME (SAVE IN PTIME) AND, IF RESTARTING,
C  WHETHER IT'S TOO SOON (SAVE IN SOON).  PRIME-TIME SPECS ARE IN WKDAY, WKEND,
C  AND HOLID; SEE MAINT ROUTINE FOR DETAILS.  LATNCY IS REQUIRED DELAY BEFORE
C  RESTARTING.  WIZARDS MAY CUT THIS TO A THIRD.

      CALL DATIME(D,T)
      PRIMTM=WKDAY
      IF(MOD(D,7).LE.1)PRIMTM=WKEND
      IF(D.GE.HBEGIN.AND.D.LE.HEND)PRIMTM=HOLID
      PTIME=(PRIMTM.AND.SHIFT(1,T/60)).NE.0
      SOON=.FALSE.
      IF(SETUP.GE.0)GOTO 20
      DELAY=(D-SAVED)*1440+(T-SAVET)
      IF(DELAY.GE.LATNCY)GOTO 20
      TYPE 10,DELAY
10    FORMAT(' This adventure was suspended a mere',I3,' minutes ago.')
      SOON=.TRUE.
      IF(DELAY.GE.LATNCY/3)GOTO 20
      CALL MSPEAK(2)
      STOP

C  IF NEITHER TOO SOON NOR PRIME TIME, NO PROBLEM.  ELSE SPECIFY WHAT'S WRONG.

20    START=.FALSE.
      IF(SOON)GOTO 30
      IF(PTIME)GOTO 25
22    SAVED=-1
      RETURN

C  COME HERE IF NOT RESTARTING TOO SOON (MAYBE NOT RESTARTING AT ALL), BUT IT'S
C  PRIME TIME.  GIVE OUR HOURS AND SEE IF HE'S A WIZARD.  IF NOT, THEN CAN'T
C  RESTART, BUT IF JUST BEGINNING THEN WE CAN OFFER A SHORT GAME.

25    CALL MSPEAK(3)
      CALL HOURS
      CALL MSPEAK(4)
      IF(WIZARD(0))GOTO 22
      IF(SETUP.LT.0)GOTO 33
      START=YESM(5,7,7)
      IF(START)GOTO 22
      STOP

C  COME HERE IF RESTARTING TOO SOON.  IF HE'S A WIZARD, LET HIM GO (AND NOTE
C  THAT IT THEN DOESN'T MATTER WHETHER IT'S PRIME TIME).  ELSE, TOUGH BEANS.

30    CALL MSPEAK(8)
      IF(WIZARD(0))GOTO 22
33    CALL MSPEAK(9)
      STOP
      END



      SUBROUTINE MAINT

C  SOMEONE SAID THE MAGIC WORD TO INVOKE MAINTENANCE MODE.  MAKE SURE HE'S A
C  WIZARD.  IF SO, LET HIM TWEAK ALL SORTS OF RANDOM THINGS, THEN EXIT SO CAN
C  SAVE TWEAKED VERSION.  SINCE MAGIC WORD MUST BE FIRST COMMAND GIVEN, ONLY
C  THING WHICH NEEDS TO BE FIXED UP IS ABB(1).

      IMPLICIT INTEGER(A-Z)
      LOGICAL YESM,BLKLIN
      DIMENSION HNAME(4),ABB(150)
      COMMON /BLKCOM/ BLKLIN
      COMMON /ABBCOM/ ABB
      COMMON /WIZCOM/ WKDAY,WKEND,HOLID,HBEGIN,HEND,HNAME,
     1SHORT,MAGIC,MAGNM,LATNCY,SAVED,SAVET,SETUP

      IF(.NOT.WIZARD(0))RETURN
      BLKLIN=.FALSE.
      IF(YESM(10,0,0))CALL HOURS
      IF(YESM(11,0,0))CALL NEWHRS
      IF(.NOT.YESM(26,0,0))GOTO 10
      CALL MSPEAK(27)
      ACCEPT 1,HBEGIN
1     FORMAT(G)
      CALL MSPEAK(28)
      ACCEPT 1,HEND
      CALL DATIME(D,T)
      HBEGIN=HBEGIN+D
      HEND=HBEGIN+HEND-1
      CALL MSPEAK(29)
      ACCEPT 2,HNAME
2     FORMAT(4A5)
10    TYPE 12,SHORT
12    FORMAT(' Length of short game (null to leave at',I3,'):')
      ACCEPT 1,X
      IF(X.GT.0)SHORT=X
      CALL MSPEAK(12)
      CALL GETIN(X,Y,Y,Y)
      IF(X.NE.' ')MAGIC=X
      CALL MSPEAK(13)
      ACCEPT 1,X
      IF(X.GT.0)MAGNM=X
      TYPE 16,LATNCY
16    FORMAT(' Latency for restart (null to leave at',I3,'):')
      ACCEPT 1,X
      IF(X.GT.0.AND.X.LT.45)CALL MSPEAK(30)
      IF(X.GT.0)LATNCY=MAX0(45,X)
      IF(YESM(14,0,0))CALL MOTD(.TRUE.)
      SAVED=0
      SETUP=2
      ABB(1)=0
      CALL MSPEAK(15)
      BLKLIN=.TRUE.
      CALL CIAO
      END



      LOGICAL FUNCTION WIZARD(DUMMY)

C  ASK IF HE'S A WIZARD.  IF HE SAYS YES, MAKE HIM PROVE IT.  RETURN TRUE IF HE
C  REALLY IS A WIZARD.

      IMPLICIT INTEGER(A-Z)
      LOGICAL YESM
      DIMENSION HNAME(4),VAL(5)
      COMMON /WIZCOM/ WKDAY,WKEND,HOLID,HBEGIN,HEND,HNAME,
     1SHORT,MAGIC,MAGNM,LATNCY,SAVED,SAVET,SETUP

      WIZARD=YESM(16,0,7)
      IF(.NOT.WIZARD)RETURN

C  HE SAYS HE IS.  FIRST STEP: DOES HE KNOW ANYTHING MAGICAL?

      CALL MSPEAK(17)
      CALL GETIN(WORD,X,Y,Z)
      IF(WORD.NE.MAGIC)GOTO 99

C  HE DOES.  GIVE HIM A RANDOM CHALLENGE AND CHECK HIS REPLY.

      CALL DATIME(D,T)
      T=T*2+1
      WORD='@@@@@'
      DO 15 Y=1,5
      X=79+MOD(D,5)
      D=D/5
      DO 12 Z=1,X
12    T=MOD(T*1027,1048576)
      VAL(Y)=(T*26)/1048576+1
15    WORD=WORD+SHIFT(VAL(Y),36-7*Y)
      IF(YESM(18,0,0))GOTO 99
      TYPE 18,WORD
18    FORMAT(/1X,A5)
      CALL GETIN(WORD,X,Y,Z)
      CALL DATIME(D,T)
      T=(T/60)*40+(T/10)*10
      D=MAGNM
      DO 19 Y=1,5
      Z=MOD(Y,5)+1
      X=MOD(IABS(VAL(Y)-VAL(Z))*MOD(D,10)+MOD(T,10),26)+1
      T=T/10
      D=D/10
19    WORD=WORD-SHIFT(X,36-7*Y)
      IF(WORD.NE.'@@@@@')GOTO 99

C  BY GEORGE, HE REALLY *IS* A WIZARD!

      CALL MSPEAK(19)
      RETURN

C  AHA!  AN IMPOSTOR!

99    CALL MSPEAK(20)
      WIZARD=.FALSE.
      RETURN
      END



      SUBROUTINE HOURS

C  ANNOUNCE THE CURRENT HOURS WHEN THE CAVE IS OPEN FOR ADVENTURING.  THIS INFO
C  IS STORED IN WKDAY, WKEND, AND HOLID, WHERE BIT SHIFT(1,N) IS ON IFF THE
C  HOUR FROM N:00 TO N:59 IS "PRIME TIME" (CAVE CLOSED).  WKDAY IS FOR
C  WEEKDAYS, WKEND FOR WEEKENDS, HOLID FOR HOLIDAYS.  NEXT HOLIDAY IS FROM
C  HBEGIN TO HEND.

      IMPLICIT INTEGER(A-Z)
      DIMENSION HNAME(4),VAL(5)
      COMMON /WIZCOM/ WKDAY,WKEND,HOLID,HBEGIN,HEND,HNAME

      TYPE 1
1     FORMAT()
      CALL HOURSX(WKDAY,'Mon -',' Fri:')
      CALL HOURSX(WKEND,'Sat -',' Sun:')
      CALL HOURSX(Holid,'Holid','ays: ')
      CALL DATIME(D,T)
      IF(HEND.LT.D.OR.HEND.LT.HBEGIN)RETURN
      IF(HBEGIN.GT.D)GOTO 10
      TYPE 5,HNAME
5     FORMAT(/' Today is a holiday, namely ',4A5)
      RETURN

10    D=HBEGIN-D
      T='Days,'
      IF(D.EQ.1)T='Day, '
      TYPE 15,D,T,HNAME
15    FORMAT(/' The next holiday will be in',I3,' ',A5,' namely ',4A5)
      RETURN
      END



      SUBROUTINE HOURSX(H,DAY1,DAY2)

C  USED BY HOURS (ABOVE) TO PRINT HOURS FOR EITHER WEEKDAYS OR WEEKENDS.

      IMPLICIT INTEGER(A-Z)
      LOGICAL FIRST

      FIRST=.TRUE.
      FROM=-1
      IF(H.NE.0)GOTO 10
      TYPE 2,DAY1,DAY2
2     FORMAT(10X,2A5,'  Open all day')
      RETURN

10    FROM=FROM+1
      IF((H.AND.SHIFT(1,FROM)).NE.0)GOTO 10
      IF(FROM.GE.24)GOTO 20
      TILL=FROM
14    TILL=TILL+1
      IF((H.AND.SHIFT(1,TILL)).EQ.0.AND.TILL.NE.24)GOTO 14
      IF(FIRST)TYPE 16,DAY1,DAY2,FROM,TILL
      IF(.NOT.FIRST)TYPE 18,FROM,TILL
16    FORMAT(10X,2A5,I4,':00 to',I3,':00')
18    FORMAT(20X,I4,':00 to',I3,':00')
      FIRST=.FALSE.
      FROM=TILL
      GOTO 10

20    IF(FIRST)TYPE 22,DAY1,DAY2
22    FORMAT(10X,2A5,'  Closed all day')
      RETURN
      END



      SUBROUTINE NEWHRS

C  SET UP NEW HOURS FOR THE CAVE.  SPECIFIED AS INVERSE--I.E., WHEN IS IT
C  CLOSED DUE TO PRIME TIME?  SEE HOURS (ABOVE) FOR DESC OF VARIABLES.

      IMPLICIT INTEGER(A-Z)
      DIMENSION HNAME(4)
      COMMON /WIZCOM/ WKDAY,WKEND,HOLID,HBEGIN,HEND,HNAME

      CALL MSPEAK(21)
      WKDAY=NEWHRX('Weekd','ays:')
      WKEND=NEWHRX('Weeke','nds:')
      HOLID=NEWHRX('Holid','ays:')
      CALL MSPEAK(22)
      CALL HOURS
      RETURN
      END



      INTEGER FUNCTION NEWHRX(DAY1,DAY2)

C  INPUT PRIME TIME SPECS AND SET UP A WORD OF INTERNAL FORMAT.

      IMPLICIT INTEGER(A-Z)

      NEWHRX=0
      TYPE 1,DAY1,DAY2
1     FORMAT(' Prime time on ',2A5)
10    TYPE 2
2     FORMAT(' from:')
      ACCEPT 3,FROM
3     FORMAT(G)
      IF(FROM.LT.0.OR.FROM.GE.24)RETURN
      TYPE 4
4     FORMAT(' till:')
      ACCEPT 3,TILL
      TILL=TILL-1
      IF(TILL.LT.FROM.OR.TILL.GE.24)RETURN
      DO 5 I=FROM,TILL
      IDONDX=I
5     NEWHRX=(NEWHRX.OR.SHIFT(1,IDONDX))
      GOTO 10
      END



      SUBROUTINE MOTD(ALTER)

C  HANDLES MESSAGE OF THE DAY.  IF ALTER IS TRUE, READ A NEW MESSAGE FROM THE
C  WIZARD.  ELSE PRINT THE CURRENT ONE.  MESSAGE IS INITIALLY NULL.

      IMPLICIT INTEGER(A-Z)
      LOGICAL ALTER
      DIMENSION MSG(100)
      DATA MSG/100*-1/

      IF(ALTER)GOTO 50

      K=1
10    IF(MSG(K).LT.0)RETURN
      TYPE 20,(MSG(I),I=K+1,MSG(K)-1)
20    FORMAT(' ',14A5)
      K=MSG(K)
      GOTO 10

50    M=1
      CALL MSPEAK(23)
55    ACCEPT 56,(MSG(I),I=M+1,M+14),K
56    FORMAT(15A5)
      IF(K.EQ.' ')GOTO 60
      CALL MSPEAK(24)
      GOTO 55
60    DO 62 I=1,14
      K=M+15-I
      IF(MSG(K).NE.' ')GOTO 65
62    CONTINUE
      GOTO 90
65    MSG(M)=K+1
      M=K+1
      IF(M+14.LT.100)GOTO 55
      CALL MSPEAK(25)
90    MSG(M)=-1
      RETURN
      END



      SUBROUTINE POOF

C  AS PART OF DATABASE INITIALISATION, WE CALL POOF TO SET UP SOME DUMMY
C  PRIME-TIME SPECS, MAGIC WORDS, ETC.

      IMPLICIT INTEGER(A-Z)
      DIMENSION HNAME(4)
      COMMON /WIZCOM/ WKDAY,WKEND,HOLID,HBEGIN,HEND,HNAME,
     1SHORT,MAGIC,MAGNM,LATNCY,SAVED,SAVET,SETUP

      WKDAY="00777400
      WKEND=0
      HOLID=0
      HBEGIN=0
      HEND=-1
      SHORT=30
      MAGIC='DWARF'
      MAGNM=11111
      LATNCY=90
      RETURN
      END
      C  UTILITY ROUTINES (SHIFT, RAN, DATIME, CIAO, BUG)


      INTEGER FUNCTION SHIFT(VAL,DIST)
      IMPLICIT INTEGER(A-Z)

C  RETURN VAL LEFT-SHIFTED (LOGICALLY) DIST BITS (RIGHT-SHIFT IF DIST<0).

      SHIFT=VAL
      IF(DIST)10,20,30
10    IDIST=-DIST
      DO 11 I=1,IDIST
      J=0
      IF(SHIFT.LT.0)J="200000000000
11    SHIFT=((SHIFT.AND."377777777777)/2)+J
20    RETURN
30    DO 31 I=1,DIST
      J=0
      IF((SHIFT.AND."200000000000).NE.0)J="400000000000
31    SHIFT=(SHIFT.AND."177777777777)*2+J
      RETURN
      END



      INTEGER FUNCTION RAN(RANGE)

C  SINCE THE RAN FUNCTION IN LIB40 SEEMS TO BE A REAL LOSE, WE'LL USE ONE OF
C  OUR OWN.  IT'S BEEN RUN THROUGH MANY OF THE TESTS IN KNUTH VOL. 2 AND
C  SEEMS TO BE QUITE RELIABLE.  RAN RETURNS A VALUE UNIFORMLY SELECTED
C  BETWEEN 0 AND RANGE-1.  NOTE RESEMBLANCE TO ALG USED IN WIZARD.

      IMPLICIT INTEGER(A-Z)
      DATA R/0/

      D=1
      IF(R.NE.0)GOTO 1
      CALL DATIME(D,T)
      R=18*T+5
      D=1000+MOD(D,1000)
1     DO 2 T=1,D
2     R=MOD(R*1021,1048576)
      RAN=(RANGE*R)/1048576
      RETURN
      END



      SUBROUTINE DATIME(D,T)

C  RETURN THE DATE AND TIME IN D AND T.  D IS NUMBER OF DAYS SINCE 01-JAN-77,
C  T IS MINUTES PAST MIDNIGHT.  THIS IS HARDER THAN IT SOUNDS, BECAUSE THE
C  FINAGLED DEC FUNCTIONS RETURN THE VALUES ONLY AS ASCII STRINGS!

      IMPLICIT INTEGER(A-Z)
      DIMENSION DAT(2),MONTHS(12),HATH(12)
      DATA MONTHS/'-JAN-','-FEB-','-MAR-','-APR-','-MAY-','-JUN-',
     1'-JUL-','-AUG-','-SEP-','-OCT-','-NOV-','-DEC-'/
      DATA HATH/31,28,31,30,31,30,31,31,30,31,30,31/

C  FUNCTION I2 TAKES 2-DIGIT ASCII AND YIELDS DECIMAL VALUE.

      I2(X)=(SHIFT(X,-29).AND.15)*10+(SHIFT(X,-22).AND.15)

      CALL DATE(DAT)
      CALL TIME(TIM)

      YEAR=I2(SHIFT(DAT(2),14))-77
      D=I2(DAT(1))-1
      X=((SHIFT(DAT(1),14).OR.SHIFT(DAT(2),-21)).AND..NOT."1004020001)
     1.OR.'-@@@-'
C  ABOVE FUNNY EXPRESSION GUARANTEES (A) UPPER-CASE, AND (B) BOTTOM BIT OKAY.
      DO 1 MON=1,12
      IF(X.EQ.MONTHS(MON))GOTO 2
1     D=D+HATH(MON)
      CALL BUG(28)

2     D=D+YEAR*365+YEAR/4
      IF(MOD(YEAR,4).EQ.3.AND.MON.GT.2)D=D+1
      T=I2(TIM)*60+I2(SHIFT(TIM,21))
      RETURN
      END



      SUBROUTINE CIAO

C  EXITS, AFTER ISSUING REMINDER TO SAVE NEW CORE IMAGE.  USED WHEN SUSPENDING
C  AND WHEN CREATING NEW VERSION VIA MAGIC MODE.  ON SOME SYSTEMS, THE CORE
C  IMAGE IS LOST ONCE THE PROGRAM EXITS.  IF SO, SET K=31 INSTEAD OF 32.

      IMPLICIT INTEGER(A-Z)
      DATA K/32/

      CALL MSPEAK(K)
      IF(K.EQ.31)CALL GETIN(A,B,C,D)
      STOP
      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' Probable cause: erroneous info in database.'/
     2' Error code =',I2/)
      STOP
      END