Google
 

Trailing-Edge - PDP-10 Archives - SRI_NIC_PERM_SRC_3_19910112 - utilities/cave.mac
There are no other files named cave.mac in the archive.
	TITLE	CAVE	ANOTHER GAME TO EXPLORE DUNGEONS
	SUBTTL	COMMENTS/DAVID I. BELL/DZN




;THIS IS A PSEUDO-DUNGEON CAVE EXPLORATION PROGRAM.  THIS IS MUCH
;SIMPLER THAN ALL THE VARIOUS DUNGEON PROGRAMS NOW IN EXISTANCE.
;HOWEVER, THERE ARE THREE BIG FEATURES IN THIS PARTICULAR PROGRAM,
;WHICH IS THE MAJOR REASON FOR WRITING IT.  THESE ARE:
;
;1.	PLAYERS WILL COMPETE AGAINST EACH OTHER IN EXPLORING THE
;	DUNGEON, KILLING MONSTERS, AND COLLECTING TREASURE.
;	THE PROGRAM WILL BE ABLE TO LIST THE PLAYERS AND THEIR
;	ACCOMPLISHMENTS.
;
;2.	THE DUNGEON IS DYNAMICALLY ALLOCATED AS THE PLAYERS EXPLORE
;	NEW PATHS.  THUS NOBODY WILL EVER BE ABLE TO COMPLETELY MAP
;	THE DUNGEON, SINCE IT GROWS FOREVER.  THIS MEANS THAT NEW
;	PLAYERS WILL HAVE A CHANCE TO DISCOVER NEW STUFF, AND THE
;	OLD PLAYERS WON'T RUN OUT OF STUFF TO DO.
;
;3.	LIKE THE REAL GAME OF DUNGEONS AND DRAGONS (WHICH I HAVE NEVER
;	PLAYED), THIS DUNGEON CONSISTS OF MANY LEVELS, WHERE THE
;	DEEPER THE LEVEL, THE TOUGHER THE MONSTERS ARE AND THE GREATER
;	THE VALUE OF THE TREASURE YOU FIND.  PLAYERS CAN ONLY GO TO THE
;	DEEPER LEVELS AS THEY GAIN EXPERIENCE AT THE EASIER LEVELS.
	SUBTTL	DEFINITIONS




	SEARCH	MONSYM,MACSYM	;GET DEFINITIONS
	SALL			;MAKE NICE LOOKING MACROS




;VERSION INFORMATION:


	VMAJOR==1	;MAJOR VERSION
	VMINOR==0	;MINOR VERSION
	VEDIT==100	;EDIT NUMBER
	VWHO==4		;WHO LAST EDITED



;ACCUMULATORS:


	F=0		;FLAGS
	T1=1		;TEMPORARY AC'S
	T2=2
	T3=3
	T4=4
	I=5		;RANDOM INDEX
	U=6		;ADDRESS OF USER DATA
	R=7		;ADDRESS OF CURRENT ROOM DATA
	S=10		;ADDRESS OF NEW ROOM DATA
	C=11		;CHARACTER AC
	ZR=12		;AC USED FOR TESTING FOR ROOM ZERO
	PL=13		;LEVEL WE'RE PLOTTING
	PR=14		;ROOM WE'RE PLOTTING
	P=17		;STACK POINTER
;FLAG BITS IN AC F:


	FR.GOD==1	;WE ARE A PRIVILEGED PLAYER
	FR.PLY==2	;THE PLAY COMMAND HAS BEEN GIVEN
	FR.BLD==4	;COMMAND TABLE NEEDS TO BE REBUILT
	FR.DEB==10	;DEBUGGING INFORMATION IS TYPED OUT
	FR.VRB==20	;VERBOSE OUTPUT IS DESIRED
	FR.VR2==40	;VERBOSE OUTPUT DESIRED, BUT TEMPORARILY
	FR.LCK==100	;THE DATA FILE IS LOCKED
	FR.FND==200	;SOMETHING WAS FOUND IN THIS ROOM
	FR.KIL==400	;DEFAULT COMMAND IS TO BE "KILL"
	FR.TMP==1000	;TEMPORARY USE FOR LOOPS
	FR.CRL==2000	;CRLFS IN OUTPUT ARE REAL
	FR.MAP==4000	;THE DATA FILE IS OPENED AND MAPPED

	INIFLG==FR.BLD!FR.VRB	;INITIAL FLAGS ON STARTUP



;OTHER DEFINITIONS:


	GODUSR==20	;USER WHICH IS GODLY BY DEFAULT
	USRLH==500000	;LEFT HALFS OF USER NUMBERS
	HDRVER==3	;VERSION OF THE DATA FILE
	PLRMAX==^D100	;NUMBER OF PLAYERS WHO CAN PLAY
	PDLSIZ==30	;STACK SIZE
	TXTLEN==^D200	;SIZE OF COMMAND BUFFERS
	COLMIN==^D60	;MINIMUM WIDTH OF TERMINAL
	COLMAX==^D200	;MAXIMUM WIDTH
	TTYMAX==^D60	;COLUMN WHEN CRLF IS TO BE DONE
	PTHMAX==^D100	;WORDS USED TO STORE PATH DEFINITIONS
	PTHWID==4	;NUMBER OF BITS NEEDED TO HOLD DIRECTIONS (AND 2 MORE)
	WRDMAX==^D25	;NUMBER OF MAGIC WORDS TO GENERATE
	DEFMAX==^D100	;NUMBER OF WORDS TO HOLD PATH DEFINITIONS
	DEFWID==3	;BITS USED TO A DIRECTION IN A PATH DEFINITIONS
	ITMWID==3	;NUMBER OF BITS TO HOLD ITEM COUNTS
	SFPMAX==6	;MAXIMUM SHIFT FOR NEW ROOM IN PRIMARY DIRECTION
	SFPMIN==4	;MINIMUM SHIFT IN PRIMARY DIRECTION
	SFSMAX==1	;MAXIMUM SHIFT IN SECONDARY DIRECTION
	CONMAX==2	;DISTANCE WHERE ROOMS WILL CONNECT
	DIRMAX==4	;NUMBER OF DIRECTIONS FROM A ROOM
	PWRMAX==^D100	;HIGHEST STRENGTH OF A PLAYER
	MOVMAX==^D100	;MAXIMUM NUMBER OF MOVES IN ONE TURN
	TREMAX==^D50	;HIGHEST TREASURE PER LEVEL PER STRENGTH UNIT
	MID==^D100000	;COORDINATE OF MIDDLE OF DUNGEON
	MIN==^D50000	;MINIMUM COORDINATE TO RANDOMLY SELECT FROM
	MAPADR==100000	;ADDRESS WHERE FILE STARTS BEING MAPPED
	MAPLST==760000	;LAST ADDRESS TO MAP
	PAGSIZ==1000	;SIZE OF A PAGE
	PLTADR=MAPADR-PAGSIZ	;LOCATION OF PLOT BUFFER
	PLTPAG==PLTADR/PAGSIZ	;PAGE NUMBER OF PLOT BUFFER
	IWIDTH==^D29	;INTEGER WIDTH OF PAPER
	FWIDTH==29.0	;FLOATING POINT "
	ISTEPS==^D100	;INTEGER STEPS PER INCH
	FSTEPS==100.0	;FLOATING POINT "
	.JBUUO==40	;LOCATION WHERE LUUOS ARE STORED
	.JB41==41	;LOCATION TO XCT ON AN LUUO
;PLOTTER COMMANDS


	XY%UP==40	;RAISE PEN COMMAND
	XY%DWN==20	;LOWER PEN COMMAND
	XY%MX==10	;-X INCREMENT
	XY%PX==4	;+X INCREMENT
	XY%PY==2	;+Y INCREMENT
	XY%MY==1	;-Y INCREMENT


;DERIVED QUANTITIES:

	PLRWDS==<PLRMAX+^D35>/^D36	;WORDS NEEDED FOR BIT TABLES
	ITMMSK==<1_ITMWID>-1	;MASK FOR ITEMS
	PTHMSK==<1_PTHWID>-1	;MASK FOR PATH DEFINITIONS




	OPDEF	STROUT	[1B8]	;OUTPUT A STRING
	OPDEF	DECOUT	[2B8]	;OUTPUT A DECIMAL NUMBER
	OPDEF	OCTOUT	[3B8]	;OUTPUT AN OCTAL NUMBER
	OPDEF	DATOUT	[4B8]	;OUTPUT A STANDARD DATE
	OPDEF	CHROUT	[5B8]	;OUTPUT A SINGLE CHARACTER
	OPDEF	PUTCHR	[CALL TTYOUT]	;OUTPUT A CHARACTER IN AC C
	OPDEF	DOCRLF	[CALL TTYCRL]	;FORCE A CRLF NOW
	SUBTTL	MACROS




	DEFINE	CMMD(ARG),<		;;MACRO TO DO A GENERAL COMMAND
	MOVEI	T2,ARG
	CALL	DOCMMD
>




	DEFINE	NOISE(TEXT),<		;;MACRO FOR NOISE
	MOVEI	T2,[ASCIZ/TEXT/]
	CALL	DONOIS
>




	DEFINE	CONFRM,<		;;MACRO FOR CONFIRMING A LINE
	CALL	DOCNFM
>



	DEFINE	AA(NAME,ADDR,BITS<0>),<	;;STANDARD COMMAND TABLE MACRO
	[ASCIZ/NAME/],,[BITS,,ADDR]
>


	DEFINE	AB(NAME,ADDR),<		;;MACRO FOR ABBREVIATIONS
	[EXP CM%FW!CM%INV!CM%ABR
	 ASCIZ/NAME/],,ADDR
>


	DEFINE	AC(NAME,ADDR),<		;;THE NORMAL KEYWORD MACRO
	[ASCIZ/NAME/],,ADDR
>



	DEFINE	TEXT(STRING),<		;;MACRO FOR ASCIZ TEXT
	XLIST
	ASCIZ	@STRING@
	LIST
>



	DEFINE	FATAL(TEXT),<		;;MACRO FOR FATAL ERRORS
	CALL	[HRROI T4,[ASCIZ/
? TEXT
/]					;;GET ERROR STRING
		JRST DOFATL]		;;AND JUMP TO ERROR HANDLER
>




	DEFINE	ERROR(INST1,INST2,TEXT),<	;;MACRO FOR NORMAL ERRORS

	CALL	[			;;GO TO ERROR CODE
IFB <TEXT>,<	SETZM	ERRTXT>		;;SAY NO MESSAGE

IFNB <TEXT>,<	IFB	<INST2>,<
		MOVEI	T1,[ASCIZ/
TEXT
/]					;;GET MESSAGE WITH CRLFS
>
		IFNB	<INST2>,<
		MOVEI	T1,[ASCIZ/
TEXT/]					;;OR MESSAGE WITH NO ENDING CRLF
>
>
		MOVEM	T1,ERRTXT	;;SAVE FOR LATER
		DMOVE	T1,[EXP	<INST1>,<INST2>]
		JRST	DOERR]		;;GO TO ERROR
>
	SUBTTL	DATA FILE FORMAT



;ALL DATA ABOUT THE DUNGEON AND ITS PLAYERS IS KEPT IN ONE FILE
;WHICH IS KEPT MAPPED INTO CORE WHILE THE PROGRAM IS RUNNING.
;THE FILE IS OPENED IN THAWED MODE, SO THAT DATA IS ALWAYS CURRENT
;FOR ALL PLAYERS.  AN INTERLOCK IS USED SO THAT ONLY ONE PLAYER
;AT A TIME CAN CHANGE THE FILE.
;
;THE FILE IS DIVIDED INTO THREE PARTS.  THE FIRST PART IS THE HEADER
;AREA, WHICH DESCRIBES THE STATE OF THE DUNGEON AS A WHOLE.  THE
;MIDDLE PART CONTAINS INFORMATION ON EACH PLAYER IN THE GAME.  THE
;LAST PART CONTAINS INFORMATION ABOUT THE ROOMS OF THE DUNGEON.  ONLY
;THE THIRD PART CAN GROW, SO THAT THERE IS A LIMIT ON THE NUMBER OF
;PLAYERS WHO CAN BE PLAYING.



DEFINE	XX(NAME,SIZE<1>),<	;;MACRO TO DEFINE OFFSETS
	NAME==.XX.		;;DEFINE THIS OFFSET
	.XX.==.XX.+SIZE		;;THEN MOVE OFFSET
>


;THE HEADER AREA OF THE FILE.  SINCE THERE IS ONLY ONE OF THESE
;AREAS, THERE IS NO OFFSET.  INSTEAD WE DEFINE THE ACTUAL LOCATION
;IN CORE WHERE THE HEADER WILL BE MAPPED.


	.XX.==MAPADR		;LOCATION WHERE HEADER STARTS IN CORE
				;(WORD 0 OF THE DATA FILE)

	XX	H.VERS		;VERSION OF THIS DATA FILE
	XX	H.LOCK		;LOCK WORD, -1 IF AVAILABLE
	XX	H.LTIM		;TIME WHEN LOCK WAS LAST OBTAINED
	XX	H.LJOB		;JOB NUMBER WHICH OBTAINED THE LOCK
	XX	H.LUSR		;USER NUMBER WHO OBTAINED THE LOCK
	XX	H.DATE		;DATE WHEN DUNGEON WAS CREATED
	XX	H.UADR		;BEGINNING ADDRESS OF THE USER DATA
	XX	H.USIZ		;SIZE OF EACH USER'S DATA AREA
	XX	H.PLRS		;NUMBER OF PLAYERS
	XX	H.RADR		;BEGINNING ADDRESS OF THE ROOM DATA
	XX	H.RSIZ		;SIZE OF EACH ROOM'S DATA
	XX	H.ROOM		;NUMBER OF ROOMS IN DUNGEON
	XX	H.LEVL		;LOWEST LEVEL IN DUNGEON
	XX	H.LROM		;NUMBER OF ROOMS IN LOWEST LEVEL
	XX	H.LDOR		;NUMBER OF LEVEL DOORS DOWN FROM THIS LEVEL
	XX	H.LGRW		;HOW MANY DOORS ALLOW THIS LEVEL TO GROW
	XX	H.LDWN		;ROOMS IN LEVEL BEFORE LEVEL-CHANGE IS ALLOWED
	XX	H.LLUK		;ROOM NEXT TO FIRST LEVEL-CHANGE DOOR IN LEVEL
	XX	H.WORD		;HOW MANY MAGIC WORDS ARE IN USE
	XX	H.MONS		;NUMBER OF MONSTERS IN DUNGEON
	XX	H.XTRA,^D43	;EXTRA FOR EXPANSION


	HDRSIZ==.XX.-MAPADR	;SIZE OF THE HEADER
;DEFINITIONS FOR THE OFFSETS INTO THE SECOND SECTION OF THE FILE.
;THIS IS DATA FOR EACH PLAYER, AND IS USUALLY REFERENCED BY INDEXING
;OFF OF AC "U".  THIS SECTION IS SEARCHED LINEARLY TO FIND THE ENTRY
;FOR THE PLAYER.




	PLRADR==MAPADR+HDRSIZ	;ADDRESS IN CORE WHERE THIS SECTION STARTS
	.XX.==0			;OFFSETS START AT ZERO


	XX	U.USER		;DIRECTORY NUMBER OF THIS USER
	XX	U.BDAT		;DATE WHEN PLAYER ENTERED DUNGEON
	XX	U.LDAT		;DATE WHEN PLAYER LAST MOVED
	XX	U.ROOM		;THE CURRENT ROOM THE PLAYER IS IN
	XX	U.FLAG		;FLAGS ABOUT THE PLAYER
	XX	U.TURN		;NUMBER OF MOVES MADE BY THE PLAYER
	XX	U.BLDR		;NUMBER OF ROOMS "BUILT" BY PLAYER
	XX	U.NEWR		;NUMBER OF ROOMS VISITED
	XX	U.LEVL		;LEVEL NUMBER OF THE PLAYER
	XX	U.CTRE		;AMOUNT OF TREASURE BEING CARRIED
	XX	U.STRE		;AMOUNT OF TREASURE SAFELY BROUGHT OUT
	XX	U.MONK		;NUMBER OF MONSTERS KILLED
	XX	U.MSGT		;TIME WE SAY MESSAGE FILE WRITTEN
	XX	U.BACK		;DIRECTION TO GO BACKWARDS
	XX	U.POWR		;STRENGTH OF THE PLAYER
	XX	U.DIES		;NUMBER OF REINCARNATIONS
	XX	U.POWM		;MAXIMUM POWER
	XX	U.ITEM		;ITEMS WE ARE CARRYING
	XX	U.ITEL		;WHICH LEVELS HAVE PROVIDED ITEMS
	XX	U.PATH,PTHMAX	;STORAGE FOR PATH DEFINITIONS
	XX	U.PATN		;NAME OF PATH BEING TAKEN
	XX	U.PATI		;INDEX INTO THE PATH SEQUENCE
	XX	U.PATR		;ROOM WHERE PATH IS GOOD FROM
	XX	U.CHET		;NUMBER OF TIMES CHEATED USING MOVE COMMAND
	XX	U.TELP		;LAST ROOM WE TELEPORTED FROM
	XX	U.ROBR		;WHO HAS ROBBED US
	XX	U.XTRA,^D17	;EXTRA LOCATIONS FOR EXPANSION


	PLRSIZ==.XX.		;SIZE OF EACH PLAYER'S BLOCK


;FLAGS IN THE FLAG WORD:


	UF.OKM==1		;WE CAN MOVE ANY DIRECTION TO AVOID MONSTERS
	UF.NIV==2		;CAN'T USE INVISIBILITY ROOM HERE
;THE THIRD SECTION OF THE FILE.  THIS CONTAINS ALL OF THE ROOMS,
;WHICH ARE NUMBERED CONSECUTIVELY AS THEY ARE EXPLORED.  ROOM 0 IS
;ALWAYS THE STARTING POINT, WHERE TREASURE HAS TO BE BROUGHT BACK
;TO BE SAFE.  THE WAY THAT ROOMS ARE LINKED TO EACH OTHER DETERMINES
;THE STRUCTURE OF THE DUNGEON.  EACH ROOM HAS AN X AND Y ADDRESS WHOSE
;ONLY PURPOSE IS TO MAKE THE MAPS REASONABLE.  I.E., ROOMS WILL JOIN
;EACH OTHER IN REASONABLE WAYS.  GIVEN A ROOM NUMBER, YOU CAN COMPUTE
;WHERE IN THE FILE THE DATA FOR THAT ROOM IS.


	ROMADR==PLRADR+PLRMAX*PLRSIZ	;ADDRESS WHERE ROOMS START
	.XX.==0			;THESE ARE OFFSETS ALSO


	XX	R.ROOM		;-1 IN LEFT HALF, ROOM NUMBER IN RIGHT
	XX	R.LOC		;X AND Y COORDINATE OF THIS ROOM
	XX	R.LEVL		;LEVEL NUMBER OF THIS ROOM (0-N)
	XX	R.FLAG		;FLAGS FOR THIS ROOM
	XX	R.DIRS,DIRMAX	;POINTERS TO ROOMS WHICH COME FROM HERE
	XX	R.VTRE		;AMOUNT OF VISIBLE TREASURE HERE
	XX	R.HTRE		;AMOUNT OF HIDDEN TREASURE HERE
	XX	R.VIST		;NUMBER OF TIMES ROOM HAS BEEN VISITED
	XX	R.FVIS		;FIRST VISITOR TO THIS ROOM
	XX	R.LVIS		;LAST VISITOR TO THIS ROOM
	XX	R.VISF,PLRWDS	;BIT TABLE FOR WHICH PLAYERS HAVE BEEN HERE
	XX	R.SRCF,PLRWDS	;WHICH PLAYERS KNOW SECRET DOORS HERE
	XX	R.WORD		;WHICH MAGIC WORD IS SCRAWLED IN THIS ROOM
	XX	R.TREF,PLRWDS	;WHICH PLAYERS HAVE GENERATED TREASURE HERE
	XX	R.MONS		;-1,,MONSTER TYPE OR ZERO IF NONE
	XX	R.MONH		;NUMBER OF HITS LEFT BEFORE CROAKING
	XX	R.MONK		;NUMBER OF DEAD MONSTERS IN THE ROOM
	XX	R.VITM		;VISIBLE ITEMS IN THIS ROOM
	XX	R.HITM		;INVISIBLE ITEMS IN THIS ROOM
	XX	R.DIES		;NUMBER OF PLAYERS WHO DIED HERE
	XX	R.KILF,PLRWDS	;WHO HAS KILLED MONSTERS IN THIS ROOM
	XX	R.HIDF,PLRWDS	;WHICH PLAYERS KNOW ABOUT HIDDEN TREASURE
	XX	R.XTRA,^D4	;EXTRA WORDS


	ROMSIZ==.XX.		;SIZE OF DATA FOR A ROOM
	SUBTTL	DEFINITIONS FOR CONNECTIONS BETWEEN ROOMS




;THE WORDS IN THE ROOM DESCRIPTIONS WHICH LINK TO OTHER WORDS HAVE THE
;FOLLOWING FORMAT.  THE RIGHT HALF IS THE ROOM NUMBER THAT TAKING THIS
;DIRECTION LEADS TO (MAY BE MEANINGLESS, THOUGH).  THE LEFT HALF IS A
;CODE SAYING WHAT IS REQUIRED TO TRAVERSE THIS PATH.  THIS CODE ALSO
;AFFECTS THE OUTPUT OF THE DESCRIPTION OF THE ROOM.



	DR%DAT==777700,,0	;MASK FOR DOOR DATA
	DR%TYP==000077,,0	;MASK FOR DOOR TYPE
	DR%NXT==000000,,777777	;MASK FOR LINK TO NEXT ROOM

	DR.UNK==0		;THIS PATH HAS NOT YET BEEN DETERMINED
	DR.NEV==1		;THERE IS NO WAY TO GO THIS WAY
	DR.ALW==2		;YOU CAN ALWAYS TRAVEL THIS WAY
	DR.SRC==3		;A SECRET DOOR CAN BE FOUND BY SEARCHING
	DR.LVL==4		;DOOR CAN BE OPENED IF LEVEL IS GOOD ENOUGH
	DR.WRD==5		;THE PROPER MAGIC WORD CAN OPEN THIS DOOR
	DR.MAG==6		;A MAGIC ITEM CAN CREATE A DOOR HERE
	DR.BLK==7		;THIS PASSAGEWAY IS BLOCKED DUE TO A CAVE-IN


;THE DIRECTIONS THAT CAN BE TRAVERSED.  THESE MUST BE PAIRED SO THAT
;THE EVEN AND ODD DIRECTIONS ARE IN OPPOSITE DIRECTIONS.


	DIR.N==0		;NORTH
	DIR.S==1		;SOUTH
	DIR.E==2		;EAST
	DIR.W==3		;WEST

	DIR.BK==DIRMAX		;NOT A REAL DIRECTION, BUT NEEDED
				;TO INDICATE BACKWARDS
	SUBTTL	MAGIC ITEMS




;THE FOLLOWING MACRO DEFINES THE KINDS OF MAGICAL ITEMS WHICH CAN
;APPEAR IN THE DUNGEON.  THESE ITEMS CAN EITHER EXIST IN A ROOM,
;OR CAN BE CARRIED BY A PLAYER.  THERE IS A MAXIMUM NUMBER OF A
;PARTICULAR ITEM THAT CAN EXIST IN A ROOM OR BE CARRIED, SINCE
;ALL THE MAGIC ITEMS SHARE THE SAME WORD OF STORAGE.  ALL ACTIONS
;PERFORMED BY THESE ITEMS OCCUR "FOR FREE".  THAT IS, NO SPECIAL
;ACTION IS NECESSARY TO MAKE THESE ITEMS WORK.  YOU JUST HAVE TO
;BE CARRYING THEM.




	DEFINE	ITEMS,<			;;THE MAGICAL ITEMS FOLLOW

XX	IT.ARM,ARMOR,a suit of armor			;MAGICAL ARMOR
XX	IT.WD1,BLACK-MAGIC-WAND,a black magic wand	;FIRST MAGIC WAND
XX	IT.GLS,GLASSES,a pair of glasses		;GLASSES
XX	NOTITEM,GOLD					;GOLD
XX	IT.WD3,GREEN-MAGIC-WAND,a green magic wand	;ANOTHER ONE
XX	IT.FIX,HEALING-RING,a ring of healing		;RING OF HEALING
XX	IT.INV,INVISIBILITY-RING,an invisibility ring	;INVISIBILITY RING
XX	IT.WD4,ORANGE-MAGIC-WAND,an orange magic wand	;LAST MAGIC WAND
XX	IT.SHV,SHOVEL,a shovel				;SHOVEL
XX	IT.SWD,SWORD,a sword				;SWORD
XX	IT.TEL,TELEPORTATION-RING,a ring of teleportation	;RING
XX	IT.WD2,WHITE-MAGIC-WAND,a white magic wand	;ANOTHER
>


	DEFINE	XX(CODE,KEYWORD,TEXT),<

	IFDIF	<CODE><NOTITEM>,<
	CODE==.XX.		;SYMBOL FOR TEXT
	XLIST			;;SUPPRESS LISTING
	.XX.==.XX.+1		;;BUMP COUNTER
	LIST			;;RESTORE LISTING
>
>

	.XX.==0			;START OFF COUNTER

	ITEMS			;GENERATE ALL THE DEFINITIONS
	SUBTTL	MONSTERS WHICH APPEAR IN THE DUNGEON




;THE FOLLOWING MACRO DEFINES ALL OF THE MONSTERS WHICH CAN APPEAR.
;ARGUMENTS TO THE MACRO ARE AS FOLLOWS:
;
;	XX	TREASURE,HITS,MEANNESS,NAME
;
;THIS MACRO IS EXPANDED LATER INTO TABLES.



	DEFINE	MONS,<		;;MACRO TO DEFINE MONSTERS

XX	1,1,1,a Buzzardly Buzzard
XX	0,10,5,a Boogie Man
XX	1,1,1,a Cookie Monster
XX	1,2,6,a Giant Ant
XX	1,6,10,a Basilisk
XX	0,4,12,a Giant Beetle
XX	1,3,5,a Carrion Crawler
XX	0,10,24,a Black Pudding
XX	1,9,4,a Chimera
XX	1,8,18,a Black Dragon
XX	1,7,16,a White Dragon
XX	1,12,36,a Gold Dragon
XX	1,4,4,a Gargoyle
XX	1,10,10,a Ghost
XX	1,2,6,a Ghoul
XX	1,11,30,a Fire Giant
XX	1,7,6,a Goblin
XX	1,8,12,a Gorgon
XX	1,1,8,a Hobgoblin
XX	1,12,10,a Hydra
XX	1,4,8,a Jackalwere
XX	1,4,4,a Kobold
XX	0,4,4,a Giant Leech
XX	1,10,16,a Fire Lizard
XX	1,6,8,a Manticore
XX	1,6,8,a Minotaur
XX	1,6,12,a Mummy
XX	1,4,10,an Ogre
XX	1,1,8,an Orc
XX	0,6,8,a Giant Porcupine
XX	1,15,24,a Purple Worm
XX	0,12,20,a Roper
XX	1,5,10,a Giant Scorpion
XX	1,3,5,a Shadow
XX	1,1,6,a Skeleton
XX	1,7,8,a Spectre
XX	1,4,8,a Giant Spider
XX	0,2,8,a Giant Toad
XX	1,2,5,a Troglodyte
XX	1,6,8,a Troll
XX	1,8,10,a Vampire
XX	1,4,8,a Giant Wasp
XX	1,4,4,a Wight
XX	0,3,5,a Wolverine
XX	1,5,6,a Wraith
XX	0,2,8,a Zombie
XX	1,25,25,an unspeakable horror
>
	SUBTTL	INITIALIZATION





CAVE:	RESET			;CLEAR EVERYTHING
	MOVX	F,INIFLG	;SET UP INITIAL FLAGS
	MOVE	P,[IOWD	PDLSIZ,PDL]	;SET UP STACK POINTER
	MOVEI	ZR,-1		;INITIALIZE MASK AC
	MOVE	T1,[CALL LUUO]	;GET LUUO INSTRUCTION
	MOVEM	T1,.JB41	;SET IT UP
	SETZM	MSGJFN		;CLEAR MESSAGE JFN
	SETZM	RANNUM		;INITIALIZE RANDOM NUMBERS
	SETZM	OUTPTR		;NO STORAGE BUFFER YET
	GJINF			;READ INFORMATION ABOUT ME
	CAMN	T1,GOD		;ARE WE THE GODLY PERSON?
	TXO	F,FR.GOD	;YES, REMEMBER THAT
	MOVEM	T1,PLYUSR	;SET WHO WE ARE PLAYING AS
	MOVEM	T1,MYUSER	;AND REMEMBER WHO WE REALLY ARE
	MOVEM	T3,MYJOB	;AND WHAT JOB NUMBER I AM
	MOVEI	T1,.PRIOU	;GET SET
	MOVEI	T2,.MORLW	;TO READ THE WIDTH
	MOVEI	T3,COLMIN	;GET MINIMUM AS DEFAULT
POKHER:	MTOPR			;DO IT
	 ERJMP	.+1		;FAILED, USE DEFAULT
	CAIGE	T3,COLMIN	;TOO FEW COLUMNS?
	MOVEI	T3,COLMIN	;YES, RAISE THE WIDTH
	CAILE	T3,COLMAX	;TOO MANY COLUMNS?
	MOVEI	T3,COLMAX	;YES, LOWER THE WIDTH
	IDIVI	T3,5		;DIVIDE BY CHARACTERS TO A WORD
	ADDI	T3,BUFF		;ADD IN ADDRESS OF BUFFER
	MOVEM	T3,FULADR	;STORE FOR LATER USE
	JRST	GETCMD		;GO READ COMMANDS
	SUBTTL	SUBROUTINE TO READ A COMMAND




;HERE FOR MAIN COMMAND DISPATCH FOR THE PROGRAM.  NEVER RETURNS.



GETCMD:	TXNE	F,FR.BLD	;NEED TO REBUILD THE COMMAND TABLE?
	CALL	BLDCMD		;YES, DO THE WORK
	MOVEM	P,SAVEP		;SAVE STACK FOR REPARSING <
	HRROI	T1,[ASCIZ/CAVE>/]	;GET USUAL PROMPT
	TXNE	F,FR.KIL	;IN MIDDLE OF A BATTLE? <<
	HRROI	T1,[ASCIZ/KILL-MODE>>/]	;YES, GET OTHER PROMPT
	MOVEM	T1,CMDBLK+.CMRTY	;SET POINTER
	MOVEI	T1,CMDBLK	;POINT TO COMMAND BLOCK
	CMMD	[FLDDB. (.CMINI)]	;INITIALIZE

NEWPAR:	MOVE	P,SAVEP		;RESTORE THE STACK
	CALL	TTYINI		;INITIALIZE TERMINAL BUFFER
	MOVEI	T1,CMDBLK	;POINT TO THE COMMAND BLOCK
	MOVEI	T2,[FLDDB. (.CMKEY,,CMDTAB)]	;GET STANDARD KEYWORD FUNCTION
	TXNE	F,FR.KIL	;IN MIDDLE OF KILLING A MONSTER?
	MOVEI	T2,[FLDDB. (.CMCFM,CM%HPP+CM%SDH,,CRLF to do another "KILL",,<[FLDDB. (.CMKEY,,CMDTAB)]>)]	;YES, GET OTHER ONE
	CALL	DOCMMD		;READ COMMAND
	TXNN	F,FR.KIL	;DOING AUTOMATIC KILL COMMANDS?
	JRST	CALCMD		;NO, GO DO NORMAL ONE
	TSC	T3,T3		;YEP, SEE WHAT COMND FUNCTION WAS DONE
	JUMPN	T3,CALCMD	;GO IF KEYWORD TYPED
	MOVEI	T2,AUTOKL	;GET ROUTINE
	JRST	DOCMD		;JOIN OTHER CODE

CALCMD:	MOVE	T2,(T2)		;GET ADDRESS OF DATA
	MOVE	T2,(T2)		;THEN ADDRESS OF ROUTINE AND FLAGS
	TLNN	T2,C.STS	;IS THIS A STATUS-TYPE COMMAND?
	TXZ	F,FR.KIL	;NO, CLEAR KILL MODE
DOCMD:	CALL	(T2)		;DO THE COMMAND
	 DOCRLF			;IF NONSKIP RETURN, END IN A CRLF
	CALL	SAVPNT		;FORCE OUTPUT OUT
	JRST	GETCMD		;READ NEXT COMMAND
;TABLE OF ALL POSSIBLE COMMANDS.  THE ACTUAL TABLE OF COMMANDS IS
;BUILT AT RUNTIME BY CHECKING IF CERTAIN CONDITIONS ARE SATISFIED.
;THE FLAG FR.BLD IS SET WHENEVER THE COMMAND TABLE HAS TO BE
;CHANGED.  THE CONDITIONS FOR A COMMAND BEING AVAILABLE ARE:



	C.PLY==1	;LEGAL ONLY IF PLAY COMMAND HAS BEEN GIVEN
	C.NOP==2	;LEGAL IF PLAY COMMAND WAS NOT YET GIVEN
	C.GOD==4	;ONLY LEGAL FOR THE DUNGEON MASTER
	C.DEB==10	;LEGAL ONLY WHEN DEBUGGING


;OTHER FLAGS FOR COMMANDS:

	C.STS==20	;THIS IS A STATUS TYPE COMMAND


CMDORG:	CMDLEN,,CMDLEN			;HEADER
	AB	B,ABB5			;ABBREVIATION FOR BACK
ABB5:	AA	BACK-UP,CMDBCK,C.PLY	;MOVE BACK TO PREVIOUS ROOM
	AA	BECOME,CMDBEC,C.DEB!C.STS	;BECOME ANOTHER PLAYER
	AA	BRIEF,CMDBRF,C.PLY!C.STS	;BRIEF OUTPUT IS WANTED
	AA	DEBUG,CMDDEB,C.GOD!C.STS	;TURN DEBUGGING ON OR OFF
	AA	DEFINE,CMDDEF,C.PLY!C.STS	;DEFINE A PATH
	AA	DELETE,CMDDEL,C.PLY!C.STS	;DELETE A PATH
	AA	DROP,CMDDRP,C.PLY	;DROP SOME TREASURE
	AB	E,ABB4			;ABBREVIATION FOR EAST
ABB4:	AA	EAST,CMDMVE,C.PLY	;MOVE EAST
	AA	EXIT,CMDXIT,C.STS	;EXIT FROM PROGRAM
	AB	F,ABB6			;ABBREVIATION FOR FIND
ABB6:	AA	FIND,CMDFND,C.PLY	;FIND HIDDEN STUFF
	AA	FOLLOW,CMDFOL,C.PLY	;FOLLOW A PREDEFINED PATH
	AA	GET,CMDGET,C.PLY	;GET SOME TREASURE
	AB	H,ABB3			;ABBREVIATION FOR HELP
ABB3:	AA	HELP,CMDHLP,C.STS	;GET HELP
	AA	HIDE,CMDHID,C.PLY	;HIDE TREASURE IN THE ROOM
	AA	INFORMATION,CMDINF,C.STS	;GET INFORMATION
	AA	INITIALIZE,CMDINI,C.DEB!C.STS	;RESET THE DATA FILE
	AA	KILL,CMDKIL,C.PLY	;KILL MONSTERS
	AB	L,ABB2			;ABBREVIATION FOR LOOK
	AA	LIST,CMDLST!C.STS	;LIST STATUS OF THE GAME
ABB2:	AA	LOOK,CMDLOK,C.PLY!C.STS	;LOOK AROUND
	AA	MOVE,CMDMOV,C.GOD!C.PLY!C.STS	;MOVE TO PARTICULAR ROOM
	AA	NORTH,CMDMVN,C.PLY	;MOVE NORTH
	AA	PLAY,CMDPLY,C.NOP!C.STS	;BEGIN PLAYING THE GAME
	AA	PLOT,CMDPLT,C.PLY!C.STS	;PLOT VISITED ROOMS ON A LEVEL
	AA	PROCEED,CMDPRO,C.PLY	;PROCEED ALONG PREVIOUS PATH
	AA	REST,CMDRST,C.PLY	;REST UP
	AA	ROB,CMDROB,C.PLY	;ROB ANOTHER PLAYER
	AB	S,ABB1			;ABBREVIATION FOR SOUTH
	AA	SAY,CMDSAY,C.PLY	;SAY SOMETHING
ABB1:	AA	SOUTH,CMDMVS,C.PLY	;MOVE SOUTH
	AA	STATUS,CMDSTS,C.STS	;GIVE STATUS OF MYSELF
	AA	TYPE,CMDTYP,C.PLY!C.STS	;TYPE OUT A PATH DEFINITION
	AA	USE,CMDUSE,C.PLY	;USE A MAGIC ITEM
	AA	VERBOSE,CMDVER,C.PLY!C.STS	;VERBOSE OUTPUT
	AA	WEST,CMDMVW,C.PLY	;MOVE WEST

	CMDLEN==.-CMDORG-1		;NUMBER OF COMMANDS
	SUBTTL	THE SIMPLE COMMANDS



;HERE TO DO THE TRIVIAL COMMANDS, SUCH AS HELP AND QUIT.




CMDXIT:	NOISE	(FROM PROGRAM)	;DO NOISE
	CONFRM			;CONFIRM THE LINE
	HALTF			;LEAVE PROGRAM
	RET			;RETURN




CMDHLP:	CONFRM			;CONFIRM THE LINE
	HRROI	T1,HLPTXT	;POINT TO HELP MESSAGE
	PSOUT			;TYPE IT
	RET			;DONE
CMDPLY:	NOISE	(IN THIS DUNGEON)	;DO NOISE
	CONFRM			;THEN CONFIRM THE LINE
	CALL	FILOPN		;OPEN UP THE DATA FILE
	CALL	FINDME		;FIND ME IN THE FILE
	TXO	F,FR.PLY!FR.BLD	;WE ARE PLAYING AND COMMANDS CHANGE NOW
	TXNE	F,FR.DEB	;DEBUGGING MODE?
	JRST	LOOKVR		;YES, DON'T TYPE MESSAGE
	MOVX	T1,GJ%SHT+GJ%OLD	;GET FLAGS
	HRROI	T2,TXTNAM	;POINT TO FILENAME
	GTJFN			;TRY TO FIND THE FILE
	 ERJMP	LOOKVR		;FAILED, GO SEE WHY
	MOVEI	T2,MSGTIM	;PLACE TO REMEMBER DATE
	MOVEI	T3,1		;WANT ONE WORD
	RFTAD			;READ WHEN FILE WAS LAST WRITTEN
	MOVE	T2,U.MSGT(U)	;GET WHEN WE LAST SAW THE MESSAGE
	CAMN	T2,MSGTIM	;SAME WRITE DATE?
	JRST [	RLJFN		;YES, RELEASE FILE
		JFCL
		JRST LOOKVR]	;AND LOOK AROUND
	CALL	DOMESS		;TYPE OUT THE MESSAGE
	STROUT	[ASCIZ/- - - -
/]				;THEN SPACE DOWN
	CALL	LOCK		;LOCK UP THE FILE
	MOVE	T1,MSGTIM	;GET TIME OF LAST WRITE
	MOVEM	T1,U.MSGT(U)	;SET NEW TIME
	CALL	UNLOCK		;UNLOCK AGAIN
	JRST	LOOKVR		;THEN GO LOOK AROUND AND RETURN




CMDINF:	NOISE	(ON LATEST FEATURES AND CHANGES)	;DO NOISE
	CONFRM			;CONFIRM THE LINE
	MOVX	T1,GJ%SHT+GJ%OLD	;GET FLAGS
	HRROI	T2,TXTNAM	;POINT TO THE FILE
	GTJFN			;FIND THE FILE
	 ERROR	(,,Unable to read information file.)	;FAIL
	CALL	DOMESS		;TYPE OUT NEWEST DATA
	RET			;DONE
CMDDEB:	NOISE	(MODE TURNED)	;NOISE
	CMMD	[FLDDB. (.CMKEY,,ONOFF,,<ON>)]	;READ THE ANSWER
	HRRZ	T4,(T2)		;GET DATA HALFWORD
	CONFRM			;CONFIRM THE LINE
	SKIPN	T4		;WANTS DEBUG MODE SET?
	TXZA	F,FR.DEB	;NO, CLEAR FLAG
	TXO	F,FR.DEB	;YES, SET FLAG
	TXO	F,FR.BLD	;NEED NEW COMMAND TABLE NOW
	JRST	CPOPJ1		;SKIP RETURN TO STOP CRLFS

ONOFF:	XWD	2,2		;TWO ENTRIES
	AC	OFF,0		;OFF
	AC	ON,1		;ON





CMDMOV:	NOISE	(TO ROOM)	;TYPE NOISE
	CMMD	[FLDDB. (.CMNUM,,^D10,,<0>)]	;READ A NUMBER
	CONFRM			;THEN CONFIRM THE LINE
	SKIPL	T2		;IS ROOM NEGATIVE?
	CAML	T2,H.ROOM	;OR TOO LARGE?
	 ERROR	(,,Illegal room number)	;YES, COMPLAIN
	CALL	LOCK		;LOCK UP THE DATA FILE
	MOVEM	T2,U.ROOM(U)	;SET WHICH ROOM WE ARE IN
	SETZM	U.BACK(U)	;MOVING BACK IS ILLEGAL
	AOS	U.CHET(U)	;REMEMBER WE HAVE CHEATED AGAIN
	CALL	UNLOCK		;UNLOCK THE FILE NOW
	MOVE	R,T2		;PUT ROOM NUMBER IN RIGHT AC
	IMULI	R,ROMSIZ	;COMPUTE OFFSET INTO ROOM TABLES
	ADDI	R,ROMADR	;OFFSET TO BEGINNING OF TABLE
	JRST	LOOKVR		;AND LOOK AROUND HERE
CMDFND:	NOISE	(HIDDEN DOORWAYS AND TREASURE)	;SOME NOISE
	CONFRM			;FINISH THE LINE
	SKIPE	T4,R.MONS(R)	;ANY MONSTER IN THE ROOM?
	JRST	FNDBSY		;YES, SEARCHING NOT ALLOWED
	CALL	LOCK		;LOCK THE FILE
	MOVEI	T1,R.SRCF(R)	;GET ADDRESS OF BIT TABLE
	CALL	BITSET		;POINT AT THE PROPER BIT
	IORM	T2,(T1)		;REMEMBER THIS ROOM WAS SEARCHED
	MOVEI	T1,R.HIDF(R)	;GET ADDRESS OF OTHER BIT TABLE
	CALL	BITSET		;POINT AT PROPER BIT
	IORM	T2,(T1)		;REMEMBER WE SEARCHED FOR TREASURE TOO
	CALL	UNLOCK		;UNLOCK FILE NOW
	TXZ	F,FR.FND	;NOTHING FOUND HERE YET
	DOCRLF			;START WITH A CRLF
	CALL	FDDOOR		;LOOK FOR SECRET DOORS
	CALL	FDTRES		;AND LOOK FOR HIDDEN TREASURE
	TXNN	F,FR.FND	;WAS ANYTHING FOUND?
	STROUT	[ASCIZ/There is nothing hidden here.  /]	;NO SAY SO
	DOCRLF			;FINISH WITH A CRLF
	RET			;AND RETURN
;HERE TO LOOK FOR HIDDEN DOORS:


FDDOOR:	MOVEI	T1,DR.SRC	;GET CODE FOR SECRET DOORS
	CALL	FNDDOR		;SEE IF ANY EXIST HERE
	JUMPE	T1,CPOPJ	;IF NONE, DONE
	CALL	LKSEC2		;SHOW SECRET DOORS
	TXO	F,FR.FND	;REMEMBER SOMETHING WAS FOUND
	RET			;DONE




;HERE TO LOOK FOR HIDDEN TREASURE:


FDTRES:	SKIPN	T4,R.HTRE(R)	;ANY HIDDEN TREASURE HERE?
	RET			;NO, SAY NOTHING
	STROUT	[ASCIZ/This room has /]	;TYPE
	MOVE	T1,T4		;GET NUMBER
	CALL	GOLOUT		;OUTPUT HOW MUCH GOLD
	STROUT	[ASCIZ/ hidden in it!!!  /]	;FINISH IT
	TXO	F,FR.FND	;REMEMBER SOMETHING FOUND
	RET			;DONE



FNDBSY:	STROUT	[ASCIZ/
The /]			;START THE OUTPUT
	HRRZ	T1,MONTXT(T4)	;GET STRING FOR MONSTER
	CALL	MONOUT		;OUTPUT MONSTER NAME
	STROUT	[ASCIZ/ stops you from looking around the room.
/]				;EXPLAIN WHY HE CAN'T DO THIS
	RET			;DONE
CMDLOK:	NOISE	(AROUND)	;NOISE
	CONFRM			;CONFIRM THE LINE
	JRST	LOOKVR		;AND LOOK AROUND



CMDBRF:	TDZA	T4,T4		;WANTS BRIEF OUTPUT
CMDVER:	MOVX	T4,FR.VRB	;OR WANTS VERBOSE OUTPUT
	NOISE	(OUTPUT IS DESIRED)	;DO NOISE
	CONFRM			;CONFIRM THE LINE
	TXZ	F,FR.VRB	;FIRST CLEAR THE VERBOSITY FLAG
	IOR	F,T4		;THEN SET IT IF WANTED
	JRST	CPOPJ1		;SKIP RETURN SO CRLF NOT DONE
;THE HELP TEXT FOR THE HELP COMMAND:




HLPTXT:	TEXT	<
Commands are the following:

BRIEF	Give a very short description of a room that you have seen
	before.  Anything interesting about the room will still be
	typed, such as treasure, monsters, and magic words.

DEFINE	Define a path name.  This allows you to store a sequence of
	commonly used directions that can be recalled later.  Useful
	for storing the route between levels, etc.

DELETE	Deletes a previously defined path.  If the path name of "ALL"
	is specified, all definitions are deleted.

DROP	Leave your treasure in the current room.  Since it is in the
	open, anyone wandering through the room can see it and take it.
	In order to get credit for your treasure, you must return
	it to the entrance of the dungeon and drop it there.

FIND	Search the current room carefully looking for secret passages
	and hidden treasure.  You know all secret passages forever
	once you have used FIND in a room.  But if more treasure was
	hid in a room after you have searched it, another FIND will be
	needed to see it.

FOLLOW	Traverse the named path which had been previously defined.  If
	something interesting appears along the way, the movement is
	interrupted, and can be continued with the PROCEED command.

GET	Pick up the specified treasure or magic items that are in
	the current room.

HIDE	Take your treasure and hide it in the current room.  It can
	only be found by someone if they search the room.

INFORMATION  Type out the latest news about the CAVE program.  This
	is automatically done if necessary when the PLAY command is
	given.

KILL	Attempt to kill any monster in the current room.  It can take
	many KILL commands to finish off a monster.  So this command
	puts you into a mode where each CRLF will do KILL again.

LIST	Type out a listing of all of the players in this dungeon,
	giving statistics on each player and of the dungeon as a whole.
	You can also show the statistics for just yourself.

LOOK	Give the verbose description of a particular room you are in.

REST	Wait in the current room and let your strength build up to the
	specified value.  Monsters can appear while you are resting.

PLOT	Write the file CAVE.PLT which is a binary file suitable for
	sending to a plotter.  The plot shows all of the rooms you have
	been to on a level with their proper location and connections.

ROB	Attempt to rob another player in the same room as yourself.
	If he is carrying treasure, you get some of that.  Otherwise
	you get one of his magic items.  A player can only be robbed
	once between turns.

SAY	Speak a phrase which might have a magical effect.  All phrases
	which do something can be discovered before they are needed.

STATUS	Show your current status, including what room you are in, your
	strengths, and how much treasure and magic items are being
	carried.

USE	Use the specified magical item in its normal manner.

VERBOSE Indicate that all room descriptions are to be as detailed as
	possible.  This is the default mode.
>
	SUBTTL	COMMANDS TO HANDLE TREASURES





;HERE TO HIDE OR DROP TREASURE.  IF TREASURE IS DROPPED AT THE
;ENTRANCE, IT IS SAFELY STASHED AWAY AND APPEARS IN THE STATUS
;LISTING.  OTHERWISE, IT IS LIABLE TO BE GOTTEN BY ANOTHER PLAYER.



CMDDRP:	SKIPA	T2,[Z R.VTRE(R)]	;GET INDEX FOR VISIBLE TREASURE
CMDHID:	MOVE	T2,[Z R.HTRE(R)]	;OR INDEX FOR HIDDEN TREASURE
	MOVEM	T2,TEMP		;SAVE IT AWAY
	CALL	PARITM		;READ IN HOW MUCH TREASURE TO HIDE
	SKIPL	T4		;**FOR NOW CAN ONLY DROP GOLD
	 ERROR	(,,You can only drop gold so far.)	;**TEMP
	MOVE	I,T3		;SAVE AMOUNT OF TREASURE
	CALL	LOCK		;LOCK UP THE FILE
	SKIPN	T1,U.CTRE(U)	;SEE IF WE HAVE ANY TREASURE
	 ERROR	(,,You are not carrying any treasure.)	;NO
	SKIPGE	I		;WANTS ALL TREASURE DROPPED?
	MOVE	I,T1		;YES, GET ALL WE HAVE
	CAMLE	I,T1		;SEE IF ASKING FOR TOO MUCH
	 ERROR	(,,You are not carrying that much treasure.)	;YES
	MOVN	T1,I		;GET NEGATIVE TREASURE
	ADDM	T1,U.CTRE(U)	;REDUCE HOW MUCH WE ARE CARRYING
	TDNN	ZR,R.ROOM(R)	;ROOM ZERO?
	JRST	SAFTRS		;YES, MAKE TREASURE SAFE
	ADDB	I,@TEMP		;ADD TREASURE IN AND REMEMBER TOTAL
	HRRZ	T4,TEMP		;SEE IF WE HID TREASURE
	CAIE	T4,R.HTRE	;DID WE?
	JRST	NOTHID		;NOPE, SKIP ON
	MOVEI	T1,R.HIDF+1(R)	;GET ADDRESS OF SECOND WORD OF HIDE FLAGS
	SETZM	-1(T1)		;CLEAR FIRST WORD
	HRLI	T1,-1(T1)	;FINISH BLT POINTER
	BLT	T1,R.HIDF+PLRWDS-1(R)	;NOBODY KNOWS ABOUT THIS TREASURE NOW
	MOVEI	T1,R.HIDF(R)	;GET ADDRESS OF FLAGS
	CALL	BITSET		;CREATE OUR BIT
	IORM	T2,(T1)		;THEN SAY WE KNOW ABOUT TREASURE
NOTHID:	CALL	UNLOCK		;FREE UP THE LOCK
	DOCRLF			;START WITH A CRLF
	STROUT	[ASCIZ/The room now has /]	;START OUTPUT
	MOVE	T1,I		;GET AMOUNT
	CALL	GOLOUT		;OUTPUT HOW MUCH
	CAIN	T4,R.HTRE	;HIDDEN?
	STROUT	[ASCIZ/ hidden/]	;YES
	STROUT	[ASCIZ/ in it.  /]	;FINISH
	SKIPN	T2,U.CTRE(U)	;CARRYING ANY TREASURE STILL?
	STROUT	[ASCIZ/You are carrying no treasure now.
/]				;NO, SAY SO
	JUMPE	T2,CPOPJ	;RETURN IF DONE
	STROUT	[ASCIZ/You are still carrying /]	;GET TEXT
	MOVE	T1,T2		;PUT IN RIGHT AC
	CALL	GOLOUT		;OUTPUT HOW MUCH GOLD WE HAVE
	STROUT	[ASCIZ/.
/]				;THEN A CRLF
	RET			;DONE
SAFTRS:	ADDB	I,U.STRE(U)	;ADD TO TOTAL SAFE TREASURE
	CALL	UNLOCK		;UNLOCK THE FILE
	STROUT	[ASCIZ/
Congratulations!!!  You have now safely brought out /]	;START
	MOVE	T1,I		;GET AMOUNT OF GOLD
	CALL	GOLOUT		;TYPE IT
	STROUT	[ASCIZ/!!!!
/]				;FINISH TEXT
	RET			;DONE




TRETOM:	CALL	UNLOCK		;UNLOCK FILE
	SKIPN	T4		;NO TREASURE LEFT?
	STROUT	[ASCIZ/
You cannot carry any more treasure.
/]				;YES, SAY HE IS PEGGED
	JUMPE	T4,CPOPJ	;DONE IF NO MORE TREASURE TO CARRY
	STROUT	[ASCIZ/
You can only carry /]		;START OUTPUT
	MOVE	T1,T4		;GET NUMBER
	CALL	TTYDEC		;OUTPUT IT
	SKIPE	U.CTRE(U)	;CARRYING ANY TREASURE?
	STROUT	[ASCIZ/ more/]	;YES, INCLUDE THIS
	STROUT	[ASCIZ/ gold piece/]	;MORE
	CAIE	T4,1		;ONE?
	CHROUT	"s"		;NO, MAKE PLURAL
	STROUT	[ASCIZ/.
/]				;FINISH IT
	RET			;DONE
;HERE TO PICK UP TREASURE WHICH IS LAYING AROUND IN THE ROOM.
;WE ARE ABLE TO PICK UP HIDDEN TREASURE IF THE ROOM WAS SEARCHED.



CMDGET:	CALL	PARITM		;READ IN HOW MUCH TO GET
	DMOVEM	T3,ITMWNT	;REMEMBER ITEM TYPE AND AMOUNT
	CALL	LOCK		;GET THE INTERLOCK
	SKIPE	T4,R.MONS(R)	;ANY MONSTER HERE?
	JRST	GETBSY		;YES, CAN'T DO THIS THEN
	SKIPL	T1,ITMWNT+1	;SEE IF WHAT WE WANTED WAS TREASURE
	JRST	GETITM		;NO, GO GET AN ITEM THEN
	MOVEI	T1,R.HIDF(R)	;GET ADDRESS OF THE SEARCH FLAGS
	CALL	BITSET		;COMPUTE OFFSET AND BIT
	TDNN	T2,(T1)		;HAS THIS ROOM BEEN SEARCHED?
	TDZA	T1,T1		;NO, WE KNOW OF NO HIDDEN TREASURE
	MOVE	T1,R.HTRE(R)	;YEP, GET HIDDEN TREASURE
	ADD	T1,R.VTRE(R)	;ADD IN TREASURE WE CAN SEE
	SKIPN	T1		;ANY?
	 ERROR	(,,There is no treasure here.)	;NO
	SKIPGE	I,ITMWNT	;WANTS ALL OF THE TREASURE?
	MOVE	I,T1		;YES, GET ALL THERE IS
	CAMLE	I,T1		;MAKE SURE THAT MUCH IS HERE
	 ERROR	(,,There is not that much treasure here.)	;NOPE
	MOVE	T4,U.LEVL(U)	;GET LEVEL
	IMUL	T4,U.POWR(U)	;MULTIPLY BY POWER
	IMULI	T4,TREMAX	;AND BY CONSTANT TO GET MAXIMUM WE CAN CARRY
	SUB	T4,U.CTRE(U)	;DECREMENT AMOUNT BEING CARRIED
	CAMGE	T4,I		;CAN WE CARRY THIS TOO?
	JRST	TRETOM		;NO, GO COMPLAIN
	MOVE	T1,R.VTRE(R)	;GET VISIBLE TREASURE
	MOVE	T2,R.HTRE(R)	;AND HIDDEN TREASURE
	SUB	T1,I		;DECREMENT VISIBLE TREASURE
	JUMPGE	T1,GETVOK	;PROCEED IF ENOUGH IS THERE
	ADD	T2,T1		;NEED IT ALL, REDUCE INVISIBLE TREASURE
	SETZ	T1,		;AND CLEAR VISIBLE TREASURE
GETVOK:	MOVEM	T1,R.VTRE(R)	;UPDATE VISIBLE TREASURE
	MOVEM	T2,R.HTRE(R)	;AND INVISIBLE TREASURE
	ADDM	I,U.CTRE(U)	;GIVE US THE TREASURE
	CALL	UNLOCK		;UNLOCK THE FILE
	STROUT	[ASCIZ/
You are now carrying /]		;TYPE SOME TEXT
	MOVE	T1,U.CTRE(U)	;GET HOW MUCH GOLD
	CALL	GOLOUT		;TYPE HOW MUCH
	STROUT	[ASCIZ/.
/]				;FINISH THE OUTPUT
	RET			;DONE
;HERE TO PICK UP A MAGICAL ITEM.



GETITM:	CALL	GETITR		;GET HOW MANY THE ROOM HAS
	SKIPN	T2		;ANY?
	 ERROR	(,,There are none of those here.)	;NO
	CALL	GETITU		;GET HOW MANY I HAVE NOW
	CAIN	T2,ITMMSK	;AM I FULL UP?
	 ERROR	(,,You cannot carry any more of those.)	;YES
	ADDI	T2,1		;GIVE ME ONE MORE
	CALL	PUTITU		;STORE IT
	CALL	GETITR		;GET BACK NUMBER ROOM HAS
	SOSL	T2		;DECREMENT IT
	CALL	PUTITR		;PUT BACK NEW NUMBER
	CALL	UNLOCK		;UNLOCK THE FILE
	STROUT	[ASCIZ/
Done.
/]				;SAY WE DID IT
	RET			;DONE
GETBSY:	CALL	UNLOCK		;UNLOCK THE FILE
	STROUT	[ASCIZ/
The /]				;START OUTPUT
	HRRZ	T1,MONTXT(T4)	;GET STRING
	CALL	MONOUT		;OUTPUT IT
	STROUT	[ASCIZ/ prevents you from collecting anything.
/]				;COMPLAIN
	RET			;AND RETURN
	SUBTTL	SUBROUTINE TO PARSE A MAGIC ITEM OR GOLD




;CALLED TO READ THE REST OF THE COMMAND LINE, AND RETURN WHAT THE
;USER WANTS TO TALK ABOUT.
;RETURNS:
;  +1:	PROPER AMOUNT OF GOLD OR ITEMS SPECIFIED
;	T4/	MAGIC ITEM CODE, OR -1 FOR GOLD
;	T3/	(ONLY FOR GOLD)  -1 FOR ALL OF IT, OR DESIRED AMOUNT
;THE DEFAULT INPUT IS "GOLD ALL".




PARITM:	NOISE	(ITEM)		;TYPE NOISE
	CMMD	[FLDDB. (.CMKEY,,ITMKEY,,<GOLD>)]	;READ ITEM
	HRRE	T4,(T2)		;GET POSSIBLE ITEM CODE
	JUMPL	T4,PARGOL	;IF GOLD, GO GET HOW MUCH
	CONFRM			;MAGIC ITEM, CONFIRM LINE
	RET			;DONE


PARGOL:	NOISE	(NUMBER OF PIECES)	;PROMPT FOR AMOUNT OF GOLD
	CMMD	[FLDDB. (.CMKEY,,ALLKEY,,<ALL>,[FLDDB. (.CMNUM,,^D10)])]
	TSC	T3,T3		;SEE WHAT MATCHED
	SETO	T4,		;ASSUME WANTS ALL
	JUMPE	T3,PARGOA	;GO IF RIGHT
	SKIPGE	T4,T2		;MAKE SURE SPECIFIED RIGHT AMOUNT
	 ERROR	(,,You can't use a negative amount of gold!)
PARGOA:	CONFRM			;CONFIRM THE LINE
	MOVE	T3,T4		;MOVE AMOUNT OF GOLD
	SETO	T4,		;SAY WE HAVE GOLD
	RET			;RETURN
ALLKEY:	XWD	1,1		;NUMBER OF ENTRIES
	AC	ALL,0		;JUST THIS KEYWORD




;NOW GENERATE THE KEYWORD TABLE FOR THE ITEMS:


	DEFINE	XX(CODE,KEYWORD,TEXT),<

	IFIDN	<CODE><NOTITEM>,<
	AC	KEYWORD,-1
>
	IFDIF	<CODE><NOTITEM>,<
	AC	KEYWORD,CODE
>
>



ITMKEY:	XWD	ITMKNU,ITMKNU	;NUMBER OF ENTRIES
	ITEMS			;EXPAND MACRO

	ITMKNU==.-ITMKEY-1	;NUMBER OF ITEMS IN TABLE
	SUBTTL	COMMAND TO REST UP





;THIS COMMAND IS USED TO WASTE TIME SO THAT OUR STRENGTH CAN
;IMPROVE QUICKLY.  THIS COUNTS AS MOVES.




CMDRST:	NOISE	(TO RECOVER STRENGTH UP TO)	;NOISE
	CMMD	[FLDDB. (.CMKEY,,RSTKEY,,<MAXIMUM>,[FLDDB. (.CMNUM,,^D10)])]
	TSC	T3,T3		;SEE WHICH WAS TYPED
	SKIPN	T3		;WANTS ALL?
	MOVEI	T2,PWRMAX	;YES, GET MAXIMUM
	MOVEM	T2,RSTMAX	;REMEMBER FOR LOOP
	CONFRM			;FINISH THE LINE
	CALL	TELROB		;TALK ABOUT ANY ROBBERIES
	SETZM	RSTMOV		;CLEAR NUMBER OF MOVES TAKEN
	CALL	LOCK		;LOCK UP THE FILE
	SKIPE	T4,R.MONS(R)	;ANY MONSTER IN THIS ROOM?
	JRST	RSTNOP		;YES, CAN'T REST HERE


RSTLOP:	CALL	DOFIX		;FIX US UP IF NECESSARY
	AOS	U.TURN(U)	;COUNT A TURN
	AOS	RSTMOV		;REMEMBER FOR OUTPUT
	MOVE	T1,[^D100,,^D200]	;USE THESE CHANCES OF A MONSTER
	CALL	MAKMON		;SEE IF A MONSTER SHOWED UP
	SKIPE	T4,R.MONS(R)	;DID ONE?
	JRST	RSTMON		;YES, STOP NOW!
	MOVE	T1,U.POWR(U)	;GET STRENGTH NOW
	CAMGE	T1,U.POWM(U)	;REACHED MAXIMUM?
	CAML	T1,RSTMAX	;OR REACHED MAXIMUM SPECIFIED?
	JRST	RSTDON		;YES
	JRST	RSTLOP		;NO, KEEP LOOPING

RSTDON:	GTAD			;GET TIME
	MOVEM	T1,U.LDAT(U)	;UPDATE WHEN WE LAST PLAYED
	CALL	UNLOCK		;UNLOCK THE FILE
	MOVE	T1,RSTMOV	;GET NUMBER OF TURNS
	IMULI	T1,^D50		;SLEEP TO SIMULATE RESTING
	DISMS			;A SECOND FOR EVERY 20 TURNS
	STROUT	[ASCIZ/
You used /]			;START OUTPUT
	DECOUT	RSTMOV		;SPECIFY NUMBER OF TURNS USED
	STROUT	[ASCIZ/ turn/]	;TYPE
	SOSE	RSTMOV		;EXACTLY 1?
	CHROUT	"s"		;NO, MAKE PLURAL
	STROUT	[ASCIZ/ to regain your strength.
/]				;FINISH
	RET			;DONE
RSTMON:	MOVX	T1,UF.OKM	;GET FLAG
	IORM	T1,U.FLAG(U)	;REMEMBER WE CAN GO ANY DIRECTION
	MOVE	T3,U.POWR(U)	;GET OUR STRENGTH
	CALL	UNLOCK		;UNLOCK THE FILE
	MOVE	T1,RSTMOV	;GET TIME USED
	IMULI	T1,^D50		;SCALE IT
	DISMS			;WAIT PROPER TIME
	STROUT	[ASCIZ/
While you were resting /]	;GET TEXT
	HRRZ	T1,MONTXT(T4)	;THEN ADDRESS
	CALL	TTYSTR		;OUTPUT MONSTER NAME
	STROUT	[ASCIZ/ came into the room!!  Your strength only reached /]
	DECOUT	T3		;TYPE STRENGTH
	STROUT	[ASCIZ/.
/]				;FINISH IT
	RET			;DONE




RSTNOP:	CALL	UNLOCK		;UNLOCK THE FILE
	STROUT	[ASCIZ/
You can't rest with /]	;START
	HRRZ	T1,MONTXT(T4)	;GET STRING
	CALL	TTYSTR		;TYPE MONSTER
	STROUT	[ASCIZ/ in the room!!
/]				;FINISH IT
	RET			;DONE




RSTKEY:	XWD	1,1		;TABLE
	AC	MAXIMUM,0	;ONE KEYWORD




;HERE TO TRY TO FIX US AFTER A MOVE IS MADE:


DOFIX:	MOVEI	T1,PWRMAX	;GET MAXIMUM STRENGTH
	TDNN	ZR,R.ROOM(R)	;ROOM ZERO?
	MOVEM	T1,U.POWM(U)	;YES, RESET MAXIMUM STRENGTH
	MOVE	T1,U.POWR(U)	;GET OUR STRENGTH
	CAML	T1,U.POWM(U)	;REACHED MAXIMUM?
	RET			;YES, DONE
	MOVEI	T1,3		;GET RANDOM NUMBER
	CALL	RANDOM		;TO SEE IF WE GET FIXED
	JUMPE	T1,FIXYES	;YES, GO FIX US A LITTLE
	MOVEI	T1,IT.FIX	;NO, GET CODE FOR MAGIC RING
	CALL	GETITU		;FIND OUT IF WE HAVE ONE
	SKIPE	T2		;DO WE?
FIXYES:	AOS	U.POWR(U)	;YES, FIX US A LITTLE
	RET			;DONE
	SUBTTL	COMMAND TO USE A MAGIC ITEM




;THIS COMMAND LETS THE PLAYER USE THE MAGIC ITEM OF HIS CHOICE.  SOME
;OF THEM ARE IN USE BY JUST BEING CARRIED.  BUT OTHERS, SUCH AS THE
;TELEPORATION RING AND MAGIC SHOVEL HAVE TO BE USED TO WORK.




CMDUSE:	CALL	PARITM		;READ WHAT THE ITEM IS
	SKIPGE	I,T4		;SAVE ITEM AND SEE IF GOLD
	 ERROR	(,,The only thing you can do with gold is collect it.)
	CALL	LOCK		;LOCK UP THE FILE
	MOVE	T1,I		;GET READY
	CALL	GETITU		;SEE IF WE HAVE ANY OF THIS ITEM
	SKIPN	T2		;DO I HAVE ONE?
	 ERROR	(,,You do not have one of those to use.)	;NO
	CAIN	I,IT.SHV	;THE MAGIC SHOVEL?
	JRST	USESHV		;YES, GO DIG
	CAIN	I,IT.TEL	;TELEPORTATION RING?
	JRST	USETEL		;YES, GO TELEPORT
	CAIE	I,IT.WD1	;A MAGIC WAND?
	CAIN	I,IT.WD2	;WELL?
	JRST	ISWAND		;YES
	CAIE	I,IT.WD3	;WELL?
	CAIN	I,IT.WD4	;WELL?
ISWAND:	ERROR	(,,Waving the magic wand does nothing.)
	ERROR	(,,You use that item just by having it.)	;NO
;HERE TO USE THE TELEPORTATION RING:



USETEL:	MOVE	T1,R.ROOM(R)	;GET CURRENT ROOM
	EXCH	T1,U.TELP(U)	;SET AS THE SPECIAL ROOM, GET OLD ONE
	JUMPE	T1,TELNO	;IF NO OLD ONE, DO NOTHING SPECIAL
	CAMN	T1,R.ROOM(R)	;IN THE SAME ROOM?
	JRST	TELNO		;YEP, THAT IS A LOSER
	ANDI	T1,-1		;KEEP ONLY THE ROOM NUMBER
	CALL	ENTER		;ENTER THAT ROOM NOW
	CALL	UNLOCK		;UNLOCK THE FILE
	STROUT	[ASCIZ/
Your ring glows brightly, and in an instant you are whisked into another room.
/]
	JRST	LOOKVR		;GO LOOK AROUND



TELNO:	CALL	UNLOCK		;UNLOCK THE FILE
	STROUT	[ASCIZ/
Your ring glows brightly, but nothing else happens.
/]				;SAY THIS
	RET			;AND RETURN
;HERE TO DIG WITH THE MAGIC SHOVEL:



USESHV:	MOVEI	T1,DR.BLK	;GET BLOCKED KIND OF DOOR
	CALL	FNDDOR		;SEE IF ANY OF THOSE ARE HERE
	SKIPN	T1		;ANY BLOCKED DOORS?
	 ERROR	(,,The walls around here are too hard to dig through.)
	MOVEI	T1,5		;GET NICE NUMBER
	CALL	RANDOM		;TO SEE IF WE SUCCEED THIS TIME
	JUMPE	T1,SHVSRC	;GO IF SO
	ERROR	(,,You are making some progress in digging.)

SHVSRC:	MOVEI	T1,DIRMAX	;GET MAXIMUM DIRECTIONS READY
	CALL	RANDOM		;PICK ONE
	SKIPN	DORTAB(T1)	;IS THIS DIRECTION A CAVED-IN DOOR?
	JRST	SHVSRC		;NO, LOOK SOME MORE
	MOVE	T4,T1		;REMEMBER DIRECTION
	ADDI	T1,R.DIRS(R)	;POINT TO ADDRESS
	HRLOI	T2,DR.ALW	;GET NORMAL DOOR TYPE
	MOVEM	T2,(T1)		;CHANGE CAVED IN DOOR TO NORMAL ONE!
	MOVE	T1,R.LEVL(R)	;GET LEVEL
	CAMN	T1,H.LEVL	;IS THIS ROOM IN THE LAST LEVEL?
	AOS	H.LGRW		;YES, BUMP GROWING DOORS
	CALL	UNLOCK		;UNLOCK THE FILE
	STROUT	[ASCIZ/
You opened up the cave-in that was in the /]	;START THE OUTPUT
	STROUT	@DORTXT(T4)	;TYPE DOOR DIRECTION
	STROUT	[ASCIZ/ wall!!!
/]				;FINISH
	RET			;DONE
	SUBTTL	COMMAND TO KILL MONSTERS





;THIS COMMAND IS USED TO ATTEMPT TO KILL A MONSTER.  BESIDES ADDING
;TO YOUR SCORE, KILLING MONSTERS IS NECESSARY TO GET TREASURE, CROSS
;THE ROOM, OR EXAMINE THE ROOM.  IF A BATTLE IS NOT COMPLETED, THEN
;THE FR.KIL FLAG IS SET, WHICH WILL DEFAULT THE COMMAND TO "KILL"
;FOR EASE IN FINISHING OFF THE MONSTER.




CMDKIL:	NOISE	(MONSTERS)	;DO NOISE
	CONFRM			;THEN CONFIRM THE LINE
AUTOKL:	TXO	F,FR.KIL	;PUT US INTO AUTO-KILL MODE
	CALL	LOCK		;LOCK UP THE FILE
	SKIPN	T1,R.MONS(R)	;ANY MONSTER IN THIS ROOM?
	 ERROR	(<TRZ F,FR.KIL>,,There is nothing to attack here.)
	HRRZM	T1,MONTYP	;SAVE KIND OF MONSTER
	CALL	ATTACK		;SEE HOW WELL WE CRUMP THE MONSTER
	 JRST	KILLOS		;WE GOT CRUMPED, GO DAMAGE US
	SKIPN	T3,T1		;SAVE DAMAGE
	 ERROR	(,,Your blow missed completely.)	;NONE
	MOVN	T4,T1		;NEGATE DAMAGE
	ADDB	T4,R.MONH(R)	;DECREMENT HITS LEFT OF MONSTER
	JUMPLE	T4,DIDKIL	;JUMP IF WE FINISHED IT OFF
	CALL	UNLOCK		;UNLOCK THE FILE
	DOCRLF			;START WITH A CRLF
	MOVE	T1,[XWD	-STRWNU,STRWIN]	;POINT TO TABLE
	MOVE	T2,T3		;GET STRENGTH
	CALL	GIVSTR		;TYPE IT
	MOVEI	T1,[ASCIZ/The /]	;GET TEXT
	CAILE	T4,^D8		;STRONG MONSTER STILL?
	MOVEI	T1,[ASCIZ/However, the /]	;YES
	CALL	TTYSTR		;TYPE STRING
	MOVE	T1,MONTYP	;GET TYPE
	HRRZ	T1,MONTXT(T1)	;THEN TEXT
	CALL	MONOUT		;TYPE THE MONSTER NAME
	STROUT	[ASCIZ/ is /]	;THEN THIS
	MOVE	T1,[XWD	-STRMNU,STRMON]	;POINT TO TABLE
	MOVE	T2,T4		;GET STRENGTH
	CALL	GIVSTR		;OUTPUT IT
	DOCRLF			;FINISH WITH A CRLF
	RET			;DONE
;HERE IF WE FINISHED OFF THE MONSTER:


DIDKIL:	TXZ	F,FR.KIL	;WE ARE OUT OF AUTO-KILL MODE NOW
	SETZM	R.MONS(R)	;KILL OFF THE MONSTER
	SETZM	R.MONH(R)	;CLEAR THIS TOO
	MOVE	T4,MONTYP	;GET WHAT KIND OF MONSTER WAS KILLED
	SKIPL	MONTXT(T4)	;KIND OF MONSTER TO HAVE TREASURE?
	JRST	MONNOT		;NO, SKIP ON
	MOVEI	T1,2		;GET A CHANCE
	CALL	RANDOM		;COMPUTE IT
	JUMPE	T1,MONNOT	;GO ON IF NO TREASURE ANYWAY
	MOVEI	T1,R.KILF(R)	;GET ADDRESS OF FLAGS
	CALL	BITSET		;GENERATE INDEX AND MASK
	TDNE	T2,(T1)		;GOTTEN TREASURE FROM A MONSTER HERE?
	JRST	MONNOT		;YES, NO MORE
	IORM	T2,(T1)		;NOW WE HAVE
	HLRZ	T1,MONPWR(T4)	;GET DEFENSE STRENGTH
	ADD	T1,MONPWR(T4)	;ADD OFFENSE POWER
	ANDI	T1,-1		;KEEP ONLY RIGHT HALF
	IMULI	T1,^D10		;SCALE IT
	MOVE	T2,R.LEVL(R)	;GET LEVEL
	IMULI	T2,^D50		;SCALE TREASURE FOR LEVEL
	ADD	T1,T2		;ADD TO TOTAL
	ADDM	T1,R.VTRE(R)	;GIVE TREASURE TO ROOM
	CALL	RANDOM		;COMPUTE RANDOM AMOUNT
	ADDM	T1,R.VTRE(R)	;GIVE SOME MORE TOO RANDOMLY
MONNOT:	MOVEI	T1,R.HIDF(R)	;GET READY
	CALL	BITSET		;TO SEE IF WE KNOW INVISIBLE TREASURE
	TDNN	T2,(T1)		;KNOW ABOUT INVISIBLE TREASURE?
	TDZA	T3,T3		;NO, GET ZERO
	MOVE	T3,R.HTRE(R)	;YES, GET IT
	ADD	T3,R.VTRE(R)	;ADD VISIBLE TO GET TOTAL
	AOS	R.MONK(R)	;BUMP HOW MANY MONSTERS KILLED HERE
	SOS	H.MONS		;DECREMENT TOTAL MONSTERS IN CAVE
	AOS	U.MONK(U)	;ADD TO NUMBER WE HAVE KILLED
	CALL	UNLOCK		;RELEASE THE FILE
	STROUT	[ASCIZ/
Congratulations!!  You have killed /]	;TYPE SOME
	STROUT	@MONTXT(T4)	;SAY WHAT WE KILLED
	STROUT	[ASCIZ/!!!  /]	;FINISH TEXT
	SKIPN	T3		;ANY TREASURE GUARDED BY MONSTER?
	DOCRLF			;NO, TYPE A CRLF
	JUMPE	T3,CPOPJ	;DONE IF NO TREASURE
	STROUT	[ASCIZ/The monster was guarding /]	;YES, TYPE SOME
	MOVE	T1,T3		;GET NUMBER
	CALL	GOLOUT		;OUTPUT HOW MUCH
	STROUT	[ASCIZ/!!
/]				;FINISH TEXT
	RET			;RETURN SAYING BATTLE FINISHED
;HERE IF THE MONSTER HAS DAMAGED US, TO SEE WHAT HAPPENS AND DO IT:



KILLOS:	SETZM	DRPCNT		;ASSUME DROPPING NOTHING
	MOVE	T3,T1		;SAVE AMOUNT OF DAMAGE
	MOVE	T4,U.POWR(U)	;GET CURRENT STRENGTH
	SUB	T4,T1		;GET NEW STRENGTH
	JUMPLE	T4,KILDIE	;GO ON IF WE JUST DIED
	MOVEM	T4,U.POWR(U)	;SAVE NEW STRENGTH
	MOVE	T1,U.LEVL(U)	;GET OUR LEVEL
	IMUL	T1,T4		;MULTIPLY BY CURRENT STRENGTH
	IMULI	T1,TREMAX	;AND BY CONSTANT
	SUB	T1,U.CTRE(U)	;SUBTRACT WHAT WE ARE CARRYING
	JUMPGE	T1,KILNOD	;GO ON IF DON'T HAVE TO DROP ANYTHING
	ADDM	T1,U.CTRE(U)	;DROPPING NECESSARY, REDUCE AMOUNT CARRIED
	MOVM	T1,T1		;GET AMOUNT OF TREASURE DROPPED
	ADDM	T1,R.VTRE(R)	;GIVE IT TO ROOM
	MOVEM	T1,DRPCNT	;AND REMEMBER FOR TYPEOUT
KILNOD:	MOVEI	T1,5		;GET NICE NUMBER
	CALL	RANDOM		;MAKE CHANCE
	SKIPN	T1		;TIME TO REDUCE MAXIMUM?
	SOS	U.POWM(U)	;YES, REDUCE IT BY ONE
	CALL	UNLOCK		;UNLOCK THE FILE
	DOCRLF			;START WITH A CRLF
	MOVE	T1,[XWD	-STRLNU,STRLOS]	;POINT TO TABLE
	MOVE	T2,T3		;COPY HIT
	CALL	GIVSTR		;TYPE DAMAGE
	MOVEI	T1,[ASCIZ/However, you are /]	;GET TEXT
	CAIGE	T4,^D50		;HOW GOOD?
	MOVEI	T1,[ASCIZ/You are /]	;OTHER TEXT
	CALL	TTYSTR		;OUTPUT IT
	MOVE	T1,[XWD	-STRUNU,STRUS]	;POINT TO TABLE
	MOVE	T2,T4		;COPY STRENGTH
	CALL	GIVSTR		;OUTPUT IT
	SKIPN	T4,DRPCNT	;DROPPED ANY TREASURE?
	DOCRLF			;NO, TYPE CRLF
	JUMPE	T4,CPOPJ	;DONE IF NO TREASURE
	STROUT	[ASCIZ/Because you were weakened, you have had to drop /]
	MOVE	T1,T4		;GET AMOUNT
	CALL	GOLOUT		;OUTPUT IT
	STROUT	[ASCIZ/.
/]				;END THE TEXT
	RET			;DONE
;HERE IF THE MONSTER HAS KILLED US OFF.  WHAT A FATE!  WE GET MOVED
;BACK TO ROOM ZERO WITHOUT OUR TREASURE, AND HAVE TO START OVER.



KILDIE:	TXZ	F,FR.KIL	;THIS UNDOES KILL MODE
	MOVE	T1,U.CTRE(U)	;GET ALL OUR TREASURE
	SETZM	U.CTRE(U)	;REMOVE IT
	ADDM	T1,R.VTRE(R)	;AND DROP IT IN THE ROOM
	AOS	R.DIES(R)	;ONE MORE DEATH IN THIS ROOM
	SETZM	U.BACK(U)	;UNABLE TO GO BACKWARDS NOW
	SETZM	U.ROOM(U)	;BLAST US BACK TO ROOM ZERO
	MOVEI	R,ROMADR	;AND RESET POINTER TO ROOM
	AOS	U.TURN(U)	;THIS COUNTS AS A TURN
	GTAD			;GET CURRENT TIME
	MOVEM	T1,U.LDAT(U)	;UPDATE WHEN WE LAST PLAYED
	AOS	T1,U.DIES(U)	;INCREMENT NUMBER OF DEATHS FOR US
	MOVE	T4,T1		;SAVE FOR OUTPUT LATER
	IMULI	T1,5		;SCALE IT
	MOVN	T1,T1		;NEGATE IT
	ADDI	T1,^D55		;REDUCE FROM 55%
	CAIGE	T1,^D20		;GETTING LOW?
	MOVEI	T1,^D20		;YES, KEEP A MINIMUM
	MOVEM	T1,U.POWR(U)	;UPDATE OUR STRENGTH
	MOVEI	T1,PWRMAX	;GET MAXIMUM STRENGTH
	MOVEM	T1,U.POWM(U)	;AND RESET IT
	CALL	UNLOCK		;UNLOCK THE FILE
	CAIN	T4,1		;FIRST DEATH?
	STROUT	[ASCIZ/
&That last blow was too much for you!!!!  Everything turns black and
you slide into death.  Fortunately, a compassionate spirit admires
your deeds, and decides to restore your life.  So you unexpectedly
awaken back above ground at the entrance to the dungeon.  You are still
weak, however, and should not fight too much for awhile.&
/]
	CAIN	T4,2		;TWICE?
	STROUT	[ASCIZ/
&Again you have gotten yourself killed!!!!  Once again, the world
goes black and the same stupid compassionate spirit restores your
life.  You once again awaken at the entrance, and this time you
are even weaker than last time.&
/]
	CAIN	T4,3		;THREE TIMES?
	STROUT	[ASCIZ/
&For the third time, you have been killed.  And for the third time,
you are reincarnated, even weaker than before.&
/]
	CAILE	T4,3		;MORE TIMES?
	STROUT	[ASCIZ/
&Another death for you!!  Fortunately that friendly (but stupid) spirit
never gives up.  Aren't you glad!!&
/]
	RET			;AND RETURN
	SUBTTL	ROUTINE TO COMPUTE DAMAGE TO/FROM A MONSTER





;CALLED TO RETURN THE AMOUNT OF DAMAGE THAT WE HAVE DONE TO A
;MONSTER, OR THAT IT HAS DONE TO US.  DAMAGE IS ALWAYS IN THE RANGE
;ZERO TO FIVE.    RETURNS:
;  +1:	T1/  AMOUNT OF DAMAGE MONSTER DID TO US
;  +2:	T1/  AMOUNT OF DAMAGE WE DID TO MONSTER, MAYBE NONE





ATTACK:	MOVEI	T1,^D11		;GET READY
	CALL	RANDOM		;GET A RANDOM NUMBER
	SUBI	T1,5		;REDUCE AROUND ZERO
	MOVE	T4,U.LEVL(U)	;GET OUR LEVEL
	SUB	T4,R.LEVL(R)	;AND SUBTRACT LEVEL OF MONSTER
	CAILE	T4,4		;MAKE SURE IT MAKES SENSE
	MOVEI	T4,4		;SO FIX IT
	CAMGE	T4,[EXP -4]	;MAKE SURE
	HRROI	T4,-4		;IF NOT FIX IT
	ADD	T4,T1		;ADD INTO TOTAL
	SKIPGE	T4		;DO WE ATTACK OR BE ATTACKED?
	SKIPA	T1,[EXP	IT.ARM]	;GET ATTACKED, GET ARMOR CODE
	MOVEI	T1,IT.SWD	;ATTACK, GET SWORD CODE
	CALL	GETITU		;GET HOW MANY WE HAVE
	SKIPE	T2		;DO WE HAVE MAGIC HELP IN BATTLES?
	ADDI	T4,1		;YES, MAKE ODDS BETTER FOR US
	CAILE	T4,5		;NOW MAKE SURE IN GOOD RANGE
	MOVEI	T4,5		;NO, FIX IT
	CAMGE	T4,[EXP -5]	;WELL?
	HRROI	T4,-5		;FIX IT
	SKIPL	T1,T4		;MOVE TO RIGHT AC AND SEE IF WE WIN
	JRST	CPOPJ1		;YES, SKIP RETURN
	MOVM	T1,T1		;WE GET HURT, NEGATE IT
	RET			;AND RETURN
	SUBTTL	SUBROUTINE TO OUTPUT A STRENGTH TEXT



;CALLED TO GIVE THE STATUS OF A MONSTER OR US, OR THE AMOUNT OF
;DAMAGE THAT WE RECEIVED.  CALL:
;	T1/	-NUMBER OF ENTRIES,,ADDRESS OF TABLE OF TEXTS
;	T2/	STRENGTH
;PRESERVES T2.



GIVSTR:	HLRZ	T3,(T1)		;GET NEXT STRENGTH
	CAMN	T2,T3		;EXACT MATCH?
	AOJA	T1,GIVSTH	;YES, GO USE IT
	CAML	T2,T3		;LESS?
	AOBJN	T1,GIVSTR	;NO, KEEP LOOKING
GIVSTH:	HRRZ	T1,-1(T1)	;GET ADDRESS
	JRST	TTYSTR		;OUTPUT TEXT
	SUBTTL	COMMAND TO ROB ANOTHER PLAYER





;THIS COMMAND IS USED TO SWIPE TREASURE OR MAGIC ITEMS FROM ANOTHER
;PLAYER IN THE SAME ROOM AS YOURSELF.  WHAT ITEM OR TREASURE GETS
;SWIPED IS RANDOM.  A PARTICULAR PERSON CAN ONLY BE ROBBED ONCE BETWEEN
;MOVES, TO PREVENT HIM BEING TOTALLY TRASHED IF HE ISN'T PLAYING.


CMDROB:	NOISE	(THE PLAYER)	;DO NOISE
	CALL	PARUSR		;READ IN THE USER NAME
	MOVEM	T2,TEMP		;REMEMBER WHO WE ARE ROBBING
	CONFRM			;THEN CONFIRM THE LINE
	CALL	TELROB		;TELL ABOUT ANY ROBBERIES
	CALL	LOCK		;LOCK UP THE DUNGEON
	MOVE	T1,TEMP		;GET BACK USER
	CAMN	T1,PLYUSR	;TRYING TO ROB MYSELF?
	 ERROR	(,,You cannot rob yourself!!!)	;YES, LOSE
	CALL	FNDUSR		;LOOK FOR HIM
	 ERROR	(,,There is no such player in this cave.)	;FAILED
	MOVE	I,T2		;SAVE POINTER TO HIS DATA
	MOVE	T1,U.ROOM(I)	;GET ROOM HE IS IN
	CAME	T1,U.ROOM(U)	;MAKE SURE IN SAME ROOM AS US
	 ERROR	(,,That player is not here with you.)	;NOPE
	SKIPN	T1		;IN ROOM ZERO?
	 ERROR	(,,The ghost police of Teser Nigeb prevent you from robbing anyo
ne here!)
	SKIPE	R.MONS(R)	;ANY MONSTERS HERE?
	 ERROR	(,,You cannot rob anybody while there is a monster here!)
	SKIPE	U.ROBR(I)	;HAS HE ALREADY BEEN ROBBED?
	 ERROR	(,,The player was ready for another attempt at robbery and fends
 off your efforts.)
	SKIPN	T1,U.CTRE(I)	;DOES HE HAVE ANY TREASURE ON HIM?
	JRST	ROBITM		;NO, GO TRY FOR ITEMS
	CAILE	T1,^D10		;ENOUGH TREASURE TO TAKE ONLY PART OF IT?
	IDIVI	T1,3		;YES, GET 1/3 OF IT
	CAILE	T1,^D100	;IF A SMALL AMOUNT TOTAL GET IT ALL
	CALL	RANDOM		;THEN MAKE RANDOM AMOUNT
	JUMPE	T1,NOROB	;FAIL TO ROB IF ZERO
	MOVE	T2,PLYUSR	;GET WHO I AM
	MOVEM	T2,U.ROBR(I)	;REMEMBER THAT HE WAS ROBBED BY ME
	MOVN	T4,T1		;NEGATE AMOUNT
	ADDM	T4,U.CTRE(I)	;REDUCE HIS TREASURE
	ADDM	T1,U.CTRE(U)	;AND GIVE IT TO US
	CALL	UNLOCK		;UNLOCK THE FILE
	STROUT	[ASCIZ/
You have robbed the poor victim of /]	;START OUTPUT
	MOVN	T1,T4		;GET BACK AMOUNT OF GOLD SWIPED
	CALL	GOLOUT		;OUTPUT IT
	STROUT	[ASCIZ/!!
/]				;FINISH
	RET			;DONE
ROBITM:	SKIPN	U.ITEM(I)	;DOES HE HAVE ANY ITEMS TO SWIPE?
	 ERROR	(,,The player has nothing to steal!)	;NO
	MOVEI	T4,^D10		;YES, GET NUMBER OF TRIES
ROBLOP:	MOVEI	T1,ITMNUM	;NUMBER OF ITEMS POSSIBLE
	CALL	RANDOM		;PICK ONE RANDOMLY
	CALL	GETITU		;SEE HOW MANY WE HAVE ALREADY
	CAIN	T2,ITMMSK	;CAN WE CARRY ANY MORE?
	JRST	ROBNXT		;NO, TRY AGAIN
	EXCH	I,U		;POINT AT HIM TEMPORARILY
	CALL	GETITU		;THEN SEE HOW MANY HE HAS
	JUMPN	T2,ROBYES	;GO FINISH UP IF HE HAS SOME
	EXCH	U,I		;HE'S EMPTY, SWAP BACK POINTERS
ROBNXT:	SOJG	T4,ROBLOP	;TRY AGAIN
NOROB:	ERROR	(,,Your attempt at robbery failed!!)	;COMPLAIN


ROBYES:	MOVE	T3,PLYUSR	;GET WHO I AM
	MOVEM	T3,U.ROBR(U)	;REMEMBER I ROBBED HIM (AC U IS HIM HERE)
	SUBI	T2,1		;ONE LESS ITEM
	CALL	PUTITU		;UPDATE NUMBER HE HAS
	EXCH	I,U		;RESTORE CORRECT POINTERS
	CALL	GETITU		;GET NUMBER OF THEM WE HAVE
	ADDI	T2,1		;WE GET ONE MORE
	CALL	PUTITU		;GIVE IT TO US
	MOVE	T4,T1		;REMEMBER ITEM NUMBER
	CALL	UNLOCK		;UNLOCK THE FILE
	STROUT	[ASCIZ/
The player was carrying no treasure, but you did get /]	;START OUTPUT
	HRRZ	T1,ITMTAB(T4)	;GET ADDRESS OF TEXT
	CALL	TTYSTR		;OUTPUT IT
	STROUT	[ASCIZ/ instead!!
/]				;FINISH
	RET			;DONE
	SUBTTL	SUBROUTINE TO TELL ABOUT ROBBERIES




;CALLED ON EVERY NON-STATUS COMMAND TO SEE IF WE HAVE BEEN ROBBED,
;AND IF SO, TO OUTPUT THAT INFORMATION.  THIS OUTPUT OCCURS BEFORE
;THE NORMAL ACTIONS OF A COMMAND.




TELROB:	SKIPN	U.ROBR(U)	;HAVE WE BEEN ROBBED?
	RET			;NO, NOTHING TO DO
	CALL	LOCK		;YES, LOCK UP THE FILE
	MOVE	T4,U.ROBR(U)	;GET WHO ROBBED US
	SETZM	U.ROBR(U)	;CLEAR IT SO WE CAN BE ROBBED AGAIN
	CALL	UNLOCK		;UNLOCK FILE AGAIN
	JUMPE	T4,CPOPJ	;RETURN IF WE LOST THE RACE
	STROUT	[ASCIZ/
You have been robbed by /]	;OUTPUT SOME
	MOVE	T1,T4		;GET USER
	CALL	USROUT		;OUTPUT WHO IT WAS
	STROUT	[ASCIZ/ while you were not looking!!!
/]				;FINISH IT
	RET			;DONE
	SUBTTL	SUBROUTINE TO PARSE A USER NAME




;ROUTINE TO READ IN A USER NAME, AND RETURN THE USER NUMBER.  IT
;IS POSSIBLE TO READ IN A NONEXISTANT USER NUMBER BY THE USE OF
;A NUMBER-SIGN.  RETURNS USER NUMBER IN T2.



PARUSR:	CMMD	[FLDDB.	(.CMTOK,,<-1,,[ASCIZ/#/]>,,,[FLDDB. (.CMUSR)])]
	TSC	T3,T3		;SEE WHICH ONE MATCHED
	JUMPN	T3,CPOPJ	;DONE IF WAS USER NUMBER
	CMMD	[FLDDB. (.CMNUM,,^D8)]	;WAS NUMBER SIGN, GET NUMBER
	TLNN	T2,-1		;TOO LARGE?
	SKIPN	T2		;OR ZERO?
	 ERROR	(,,Illegal user number specified.)	;YES
	HRLI	T2,USRLH	;IT'S OK, FINISH USER NUMBER
	RET			;DONE
	SUBTTL	COMMAND TO SAY SOMETHING




;THIS COMMAND IS USED TO SAY SOME MAGIC WORD WHICH HOPEFULLY HAS
;A NICE EFFECT FOR THE PLAYER.  MAGIC WORDS CAN RETURN THE PLAYER
;TO THE BEGINNING OF THE DUNGEON, OPEN DOORS, OR SLAY MONSTERS,
;AS EXAMPLES.




CMDSAY:	NOISE	(THE MAGIC WORDS)	;PROMPT HIM
	CMMD	[FLDDB. (.CMTXT)]	;READ REST OF LINE
	MOVSI	T1,-SAYNUM	;GET READY FOR A LOOP
SAYSRC:	MOVEM	T1,SAYIDX	;REMEMBER IT
	CALL	@SAYTAB(T1)	;SEE IF THIS ROUTINE USES THE PHRASE
	 SKIPA	T1,SAYIDX	;NO, GET INDEX BACK
	RET			;YES, RETURN
	AOBJN	T1,SAYSRC	;NO, TRY NEXT ROUTINE
	STROUT	[ASCIZ/
Nothing happens here.
/]				;NOBODY WANTED IT, SAY THIS
	RET			;AND RETURN



;TABLE OF ROUTINES TO PARSE A PHRASE, IN THE ORDER SPECIFIED. IF A
;ROUTINE USES THE PHRASE, IT DOES WHAT ACTIONS AND TYPEOUT IT DESIRES,
;AND THEN SKIP RETURNS.  OTHERWISE IT NON-SKIPS.



SAYTAB:	EXP	SAYJNK		;SAY ONE OF THE OLD MAGIC WORDS
	EXP	SAYBEG		;SAY "TESER NIGEB" AND GO TO BEGINNING
	EXP	SAYROM		;SAY MAGIC WORD IN THIS ROOM

	SAYNUM==.-SAYTAB	;NUMBER OF ROUTINES
;ROUTINES TO CHECK THE VARIOUS CASES:



SAYBEG:	MOVEI	T1,[ASCIZ/TESER NIGEB/]	;GET STRANGE MAGIC PHRASE
	CALL	PHRASE		;DOES THIS MATCH?
	 RET			;NO, DON'T DO ANYTHING
	TDNN	ZR,R.ROOM(R)	;SAYING IT IN ROOM ZERO?
	JRST	BEGZER		;YES, SPECIAL
	CALL	LOCK		;LOCK UP THE DATA FILE
	MOVE	T1,U.CTRE(U)	;GET ALL OF OUR TREASURE
	PUSH	P,T1		;SAVE FOR LATER
	SETZM	U.CTRE(U)	;ZERO WHAT WE HAVE
	ADDM	T1,R.VTRE(R)	;GIVE IT TO THE CURRENT ROOM
	MOVEI	T1,PWRMAX	;GET FULL STRENGTH
	MOVEM	T1,U.POWM(U)	;AND FIX US ALL UP
	MOVEI	T1,0		;GET ROOM ZERO
	CALL	ENTER		;MOVE THERE
	CALL	UNLOCK		;UNLOCK THE FILE NOW
	DOCRLF			;TYPE A CRLF FIRST
	STROUT	[ASCIZ/&As you complete the magic words, a bluish haze
forms around you, and you quickly pass out.  When you awaken, you
find yourself back above ground at the entrance of the dungeon.  /]	;TYPE
	POP	P,T1		;RESTORE TREASURE DROPPED
	SKIPE	T1		;WAS ANY?
	STROUT	[ASCIZ/&(By the way, you notice that you are no longer
carrying any treasure!!)  /]	;YES, SAY SOME MORE
	DOCRLF			;DO ONE
	JRST	CPOPJ1		;AND GIVE SUCCESSFUL RETURN



BEGZER:	STROUT	[ASCIZ/
A slight breeze kicks up some dust for a minute.  But that's all.
/]				;SAY SOMETHING STRANGE
	JRST	CPOPJ1		;GOOD RETURN
SAYROM:	SKIPN	T1,R.WORD(R)	;DOES THIS ROOM HAVE A MAGIC WORD?
	RET			;NO, FORGET IT THEN
	CALL	MAKWRD		;YES, EXPAND INTO THE PHRASE
	MOVEI	T1,MAGTXT	;POINT TO BUFFER
	CALL	PHRASE		;MATCH WHAT HE TYPED?
	 RET			;NOPE, IGNORE IT
	CALL	FAULT		;PUT ALL OF THE FILE IN CORE
	CALL	LOCK		;THEN LOCK UP THE FILE
	MOVN	S,H.ROOM	;GET READY FOR SEARCH
	HRLZ	S,S		;BUILD AOBJN POINTER
	IORI	S,ROMADR	;FINISH IT
	MOVSI	I,-MOVMAX	;GET STORAGE POINTER READY

MAGSRC:	CAIN	R,(S)		;THIS SAME ROOM?
	JRST	MAGSRN		;YES, SKIP IT
	SKIPE	T1,R.WORD(S)	;THIS ROOM HAVE A MAGIC WORD TOO?
	CAME	T1,R.WORD(R)	;AND MATCH THIS ROOM'S WORD?
	JRST	MAGSRN		;NO, LOOK AT NEXT ROOM
	MOVE	T1,R.LEVL(S)	;GET LEVEL OF THE ROOM
	SUB	T1,R.LEVL(R)	;SUBTRACT CURRENT LEVEL
	MOVM	T1,T1		;GET DIFFERENCE
	CAILE	T1,2		;WITHIN A FEW LEVELS OF EACH OTHER?
	JRST	MAGSRN		;NO, SKIP IT
	MOVEI	T1,R.VISF(S)	;POINT TO VISIT FLAGS
	CALL	BITSET		;GET TEST READY
	TDNN	T2,(T1)		;HAVE WE BEEN THERE BEFORE?
	JRST	MAGSRN		;NO, IGNORE THE ROOM
	MOVEM	S,MOVLST(I)	;FOUND A CANDIDATE, SAVE IT
	AOBJP	I,MAGSRD	;IF TOO MANY, STOP NOW
MAGSRN:	ADDI	S,ROMSIZ-1	;MOVE TO NEXT ROOM
	AOBJN	S,MAGSRC	;AND CHECK IT OUT

MAGSRD:	HRRZ	T1,I		;GET NUMBER OF MATCHING ROOMS
	JUMPE	T1,SAYROF	;JUMP IF NONE
	CALL	RANDOM		;COMPUTE RANDOM NUMBER
	HRRZ	T1,MOVLST(T1)	;GET ADDRESS OF NEW ROOM
	HRRZ	T1,R.ROOM(T1)	;THEN GET ROOM NUMBER
	CALL	ENTER		;MOVE TO THAT ROOM
	CALL	UNLOCK		;UNLOCK THE FILE
	STROUT	[ASCIZ/
The room grows dim for an instant.  Then you notice you have been moved!!
/]				;TYPE SOME
	CALL	LOOKVR		;LOOK AROUND
	JRST	CPOPJ1		;AND SKIP RETURN


SAYROF:	CALL	UNLOCK		;UNLOCK THE FILE
	STROUT	[ASCIZ/
The room seems to grow dim for an instant.  But that's all.
/]				;SAY INTERESTING MESSAGE
	JRST	CPOPJ1		;GOOD RETURN
SAYJNK:	MOVSI	I,-JNKNUM	;GET READY FOR A LOOP
	HLRZ	T1,JNKTAB(I)	;GET THE PHRASE TO CHECK
	CALL	PHRASE		;DOES IT MATCH?
	 AOBJN	I,.-2		;NO, KEEP SEARCHING
	JUMPGE	I,CPOPJ		;RETURN IF NO MATCH
	HRRZ	T1,JNKTAB(I)	;GET RESPONSE
	CALL	TTYSTR		;TYPE IT
	JRST	CPOPJ1		;AND SKIP RETURN



	DEFINE	JK(TXT1,TXT2),<
	XWD	[ASCIZ/TXT1/],[ASCIZ/
TXT2
/]
>


JNKTAB:	JK	PLUGH,<A hollow voice says, "Good try, but no cigar.">
	JK	XYZZY,<You see a vision of a little dwarf throwing an axe at you
, but it quickly fades.>
	JK	Y2,<A small rock hits you on the head, with "Y2" scribbled on it
.>
	JK	ABRACADABRA,<You rise 5 feet off the ground, and then slowly set
tle back down.>
	JK	OPEN SESAME,<You hear doors opening and closing in the distance.
>

	JNKNUM==.-JNKTAB	;NUMBER OF PHRASES
;SUBROUTINE TO PARSE A STRING TO SEE IF IT MATCHES WHAT THE USER TYPED.
;THE USER'S STRING IS IN THE ATOM BUFFER.  CALL:
;  T1/	ADDRESS OF STRING TO CHECK AGAINST
;RETURNS:
;  +1:	NO MATCH
;  +2:	PHRASE MATCHED.
;
;THIS ROUTINE IGNORES EXTRA SPACES.  ALL TEMP AC'S AND "C" USED.
;LOWER CASE IS TRANSLATED TO UPPER CASE.



PHRASE:	HRLI	T1,(POINT 7,)	;FINISH BYTE POINTER TO TEST STRING
	MOVE	T2,[POINT 7,ATMBUF]	;POINT TO THE ATOM BUFFER
	MOVEI	C," "		;INITIALIZE LAST "MATCH"
PHRLP1:	ILDB	T3,T1		;GET NEXT CHAR OF TEST STRING
PHRLP2:	ILDB	T4,T2		;GET NEXT CHAR OF USER STRING
	CAIL	T4,"A"+40	;LOWER CASE LETTER?
	CAILE	T4,"Z"+40	;WELL?
	SKIPA			;NO
	SUBI	T4,40		;YES, TURN TO UPPER CASE
	CAME	T3,T4		;MATCH?
	JRST	PHRDIF		;NO, GO SEE WHY
	SKIPE	C,T3		;YES, SAVE LAST MATCH
	JRST	PHRLP1		;AND PROCEED IF NON-NULL
	JRST	CPOPJ1		;OTHERWISE THEY MATCHED

PHRDIF:	SKIPE	T3		;DIFFERENCE MAYBE OK IF TEST STRING DONE
	CAIN	C," "		;OR IF LAST MATCH WAS A SPACE
	CAIE	T4," "		;BUT CURRENT USER CHAR HAS TO BE SPACE
	RET			;NO, STRINGS DIFFER THEN
	JRST	PHRLP2		;YES, CHECK NEXT CHAR THEN
	SUBTTL	COMMAND TO GIVE STATUS OF MYSELF




;CALLED TO OUTPUT WHAT I AM CARRYING, HOW STRONG I AM, AND
;WHERE I AM IN THE DUNGEON.  ALL OF THE NICE STUFF WHICH THE
;RANDOM PLAYER WANTS TO KNOW ABOUT MYSELF.




CMDSTS:	NOISE	(ABOUT MYSELF)	;DO NOISE
	CONFRM			;AND CONFIRM THE LINE
	TXNE	F,FR.PLY	;ARE WE PLAYING?
	JRST	DOSTS		;YES, PROCEED
	CALL	FILOPN		;NOPE, OPEN UP THE DATA FILE
	MOVE	T1,PLYUSR	;GET WHO WE ARE
	CALL	FNDUSR		;LOOK FOR ME
	 ERROR	(,,You are not in this cave.)	;FAILED
	MOVE	U,T2		;OK, SET UP POINTER

DOSTS:	STROUT	[ASCIZ/
Status for player /]		;START THE OUTPUT
	MOVE	T1,U.USER(U)	;GET WHO WE ARE
	CALL	USROUT		;TYPE THE NAME
	STROUT	[ASCIZ/ at /]	;MORE OUTPUT
	HRROI	T1,TMPBUF	;POINT TO TEMPORARY BUFFER
	SETO	T2,		;TIME RIGHT NOW
	SETZ	T3,		;NORMAL OUTPUT
	ODTIM			;OUTPUT IT
	STROUT	TMPBUF		;THEN TYPE THE TEXT
	STROUT	[ASCIZ/

Current room:	   /]		;START IT OUT
	SKIPN	T4,U.ROOM(U)	;IN ROOM ZERO?
	STROUT	[ASCIZ/Entrance/]	;YES, SAY SO
	SKIPE	T1,T4		;GET NUMBER
	CALL	TTYDEC		;OUTPUT IT IF NONZERO
	JUMPE	T4,STSCON	;PROCEED IF AT ENTRANCE
	STROUT	[ASCIZ/ in level /]	;TYPE MORE
	DECOUT	R.LEVL(R)	;OUTPUT LEVEL OF CURRENT ROOM
STSCON:	STROUT	[ASCIZ/
Strength:	   /]		;START OUTPUT
	DECOUT	U.POWR(U)	;TYPE THE STRENGTH
	STROUT	[ASCIZ/ out of /]	;MORE
	DECOUT	U.POWM(U)	;TYPE MAXIMUM
	STROUT	[ASCIZ/
Reincarnations:	   /]		;SAY HOW MANY TIMES WE DIED
	SKIPN	T4,U.DIES(U)	;GET COUNT OF DEATHS
	STROUT	[ASCIZ/None/]	;NONE, SAY SO
	SKIPE	T1,T4		;MOVE TO RIGHT AC
	CALL	TTYDEC		;OUTPUT IF NONZERO
	STROUT	[ASCIZ/
Maximum level:	   /]		;MORE OUTPUT
	DECOUT	U.LEVL(U)	;TYPE IT
	STROUT	[ASCIZ/
Treasure carried:  /]		;START NEXT LINE
	SKIPN	T4,U.CTRE(U)	;ANY TREASURE?
	STROUT	[ASCIZ/None/]	;NO, SAY SO
	SKIPE	T1,T4		;WELL?
	CALL	TTYDEC		;TYPE NUMBER
	STROUT	[ASCIZ/ out of /]	;MORE
	MOVE	T1,U.LEVL(U)	;GET LEVEL
	IMUL	T1,U.POWR(U)	;MULTIPLY BY POWER
	IMULI	T1,TREMAX	;AND BY SCALE FACTOR
	CALL	GOLOUT		;OUTPUT IT
	STROUT	[ASCIZ/
Safe treasure:	   /]		;MORE
	MOVE	T4,U.STRE(U)	;GET SAFE TREASURE
	DECOUT	T4		;TYPE IT
	STROUT	[ASCIZ/ for a score of /]	;MORE
	MOVE	T1,T4		;GET TREASURE READY
	MOVE	T2,U.TURN(U)	;AND NUMBER OF TURNS
	CALL	TTYFI1		;OUTPUT IT
	STROUT	[ASCIZ/
Magic items:	   /]		;START THE OUTPUT
	SKIPN	T4,U.ITEM(U)	;ANY MAGIC ITEMS BEING CARRIED?
	STROUT	[ASCIZ/None
/]				;NO, SAY SO
	JUMPE	T4,CPOPJ	;IF NONE, ALL DONE
	TXZ	F,FR.TMP	;CLEAR TEMPORARY USE FLAG
	MOVSI	T4,-ITMNUM	;GET READY FOR A LOOP

STSITL:	HRRZ	T1,T4		;GET CODE
	CALL	GETITU		;SEE IF WE HAVE ANY
	JUMPE	T2,STSITN	;NO, SKIP ON
	TXOE	F,FR.TMP	;YES, NEED PRECEEDING TEXT?
	STROUT	[ASCIZ/		   /]	;YES, DO IT
	HRRZ	T1,ITMTAB(T4)	;GET ADDRESS
	CALL	TTYSTR		;OUTPUT NAME
	CAIN	T2,1		;MORE THAN ONE?
	JRST	STSITO		;NO, SKIP ON
	STROUT	[ASCIZ/ (/]	;YES, START MORE
	DECOUT	T2		;TYPE NUMBER
	CHROUT	")"		;FINISH
STSITO:	DOCRLF			;DO A CRLF
STSITN:	AOBJN	T4,STSITL	;LOOP UNTIL DONE
	RET			;DONE
	SUBTTL	COMMAND TO LIST THE STATUS OF THE DUNGEON




;THIS COMMAND IS USED TO LIST THE STATUS OF THE DUNGEON AND ALL
;PLAYERS IN IT.



CMDLST:	NOISE	(STATUS OF)	;NOISE
	CMMD	[FLDDB. (.CMKEY,,LSTKEY,,<EVERYONE>)]
	HRRE	T4,(T2)		;GET RESULT
	MOVEM	T4,LSTFLG	;AND SAVE IT
	CONFRM			;THEN CONFIRM THE LINE
	CALL	FILOPN		;OPEN UP THE DATA FILE
	SKIPN	LSTFLG		;WANT TO LIST EVERYONE?
	JRST	LSTALL		;YES, GO DO IT
	TXNE	F,FR.PLY	;JUST US, ARE WE PLAYING?
	JRST	LSTME		;YES, GO SHOW US
	MOVE	T1,PLYUSR	;NOPE, GET WHO WE ARE
	CALL	FNDUSR		;LOOK FOR US
	 ERROR	(,,You are not in this cave.)	;NOT THERE
	MOVE	U,T2		;REMEMBER WHERE WE ARE
	JRST	LSTME		;THEN GO LIST ME



LSTKEY:	XWD	2,2		;TWO ENTRIES
	AC	EVERYONE,0	;ALL PLAYERS
	AC	MYSELF,1	;JUST ME
LSTALL:	STROUT	[ASCIZ/
Status of dungeon created on /]	;GET SOME STRING
	DATOUT	H.DATE		;TYPE DATE DUNGEON WAS BUILT
	STROUT	[ASCIZ/

Rooms: /]			;GET READY
	MOVE	T1,H.ROOM	;GET NUMBER OF ROOMS
	SUBI	T1,1		;ACCOUNT FOR THE ENTRANCE
	DECOUT	T1		;THEN TYPE IT
	STROUT	[ASCIZ/, Highest level: /]	;MORE
	DECOUT	H.LEVL		;TYPE HIGHEST LEVEL
	STROUT	[ASCIZ/, Players: /]	;MORE TEXT
	DECOUT	H.PLRS		;TYPE HOW MANY PLAYERS EXIST
	STROUT	[ASCIZ/, Monsters: /]	;MORE
	DECOUT	H.MONS		;SAY HOW MANY
	DOCRLF			;TYPE A CRLF
	SKIPN	H.PLRS		;ANY PLAYERS TO SHOW?
	RET			;NO, DONE


LSTME:	DOCRLF			;START WITH A CRLF
	SKIPN	LSTFLG		;SHOWING EVERYONE?
	STROUT	[ASCIZ/  /]	;YES, SPACE OVER SOME
	STROUT	[ASCIZ/  Room  Turn Lev  Treas /]	;START IT
	TXNE	F,FR.DEB	;DEBUGGING?
	STROUT	[ASCIZ/Carry /]	;YES, SAY HOW MUCH CARRIED
	STROUT	[ASCIZ/ Kill/]	;MORE
	TXNE	F,FR.DEB	;WELL?
	STROUT	[ASCIZ/ Bld/]	;YES, TYPE THIS
	STROUT	[ASCIZ/ Visit  Entered   Played   Name

/]				;GET HEADER LINE
	SKIPE	LSTFLG		;WANT TO LIST JUST ME?
	JRST	LSTPLR		;YES, GO DO IT AND RETURN
	PUSH	P,U		;SAVE POINTER TO MY LOCATION
	HRLZ	U,H.PLRS	;GET NUMBER OF PLAYERS
	MOVN	U,U		;NEGATE IT
	ADDI	U,PLRADR	;RELOCATE TO RIGHT ADDRESS
PLRLOP:	SKIPN	U.USER(U)	;MAKE SURE WE HAVE A REAL USER
	TXNE	F,FR.DEB	;OR THAT WE ARE DEBUGGING
	CALL	LSTPLR		;SHOW DATA ON THIS PLAYER
	ADDI	U,PLRSIZ-1	;MOVE TO NEXT PLAYER
	AOBJN	U,PLRLOP	;LOOP FOR THEM ALL
	POP	P,U		;RESTORE ORIGINAL POINTER
	RET			;DONE
;HERE TO LIST THE STATUS OF A PARTICULAR PLAYER WHOSE DATA BLOCK
;IS POINTED TO BY AC "U":



LSTPLR:	SKIPE	LSTFLG		;LISTING ONLY MYSELF?
	JRST	NOFLME		;YES, SKIP SOME
	MOVE	T2,U.USER(U)	;GET USER NUMBER
	CAME	T2,PLYUSR	;IS THIS ME?
	CHROUT	" "		;NO, TYPE A SPACE
	CAMN	T2,PLYUSR	;WELL?
	CHROUT	"*"		;YES, SHOW ME
	CHROUT	" "		;EXTRA SPACE
NOFLME:	SKIPN	T4,U.ROOM(U)	;GET ROOM NUMBER
	STROUT	[ASCIZ/  home /]	;IF ENTRANCE, SAY SO
	SKIPN	T1,T4		;GET AGAIN
	JRST	LSHOTH		;SKIP ON
	CALL	DECSP4		;OUTPUT IT
	CHROUT	"/"		;THEN A SLASH
	MOVE	T1,U.ROOM(U)	;GET POINTER TO CURRENT ROOM
	IMULI	T1,ROMSIZ	;COMPUTE OFFSET
	MOVE	T4,ROMADR+R.LEVL(T1)	;THEN GET LEVEL
	DECOUT	T4		;TYPE IT
	CAIGE	T4,^D10		;TWO DIGITS?
	CHROUT	" "		;NO, TYPE SPACE
LSHOTH:	MOVE	T1,U.TURN(U)	;GET TURNS USED
	CALL	DECSP6		;OUTPUT IT
	MOVE	T1,U.LEVL(U)	;GET LEVEL OF PLAYER
	CALL	DECSP3		;OUTPUT IT
	MOVE	T1,U.STRE(U)	;GET SAFE TREASURE
	MOVE	T2,U.TURN(U)	;AND TURNS
	CALL	TTYFI3		;OUTPUT TREASURE PER TURN
	MOVE	T1,U.CTRE(U)	;GET AMOUNT CARRIED
	TXNE	F,FR.DEB	;DEBUGGING?
	CALL	DECSP6		;YES, SAY HOW MUCH
	MOVE	T1,U.MONK(U)	;GET NUMBER OF MONSTERS KILLED
	CALL	DECSP5		;OUTPUT IT
	MOVE	T1,U.BLDR(U)	;GET NUMBER OF ROOMS BUILT
	TXNE	F,FR.DEB	;DEBUGGING?
	CALL	DECSP5		;YES, OUTPUT IT
	MOVE	T1,U.NEWR(U)	;GET NUMBER OF ROOMS VISITED
	CALL	DECSP5		;OUTPUT IT
	CHROUT	" "		;SPACE OVER
	DATOUT	U.BDAT(U)	;TYPE OUT DATE HE BEGAN EXPLORING
	CHROUT	" "		;THEN A SPACE
	DATOUT	U.LDAT(U)	;TYPE OUT DATE HE LAST PLAYED
	STROUT	[ASCIZ/  /]	;SPACE OVER
	MOVE	T1,U.USER(U)	;GET WHO THS GUY IS
	CALL	USROUT		;AND TYPE IT
	DOCRLF			;FINISH WITH A CRLF
	RET			;DONE
	SUBTTL	COMMANDS -- PLOT (LEVEL) LEVEL-NUMBER



;HERE TO PLOT THE ROOMS ON A SPECIFIED LEVEL. ONLY THOSE ROOMS THAT THE
;PLAYER HAS VISITED ARE PLOTTED, AND ONLY HIDDEN DOORS LEADING FROM ROOMS
;IN WHICH THE PLAYER HAS TYPED 'FIND'. THUS, THE MAP WILL SHOW ONLY AS
;MUCH OF THE LEVEL AS THE PLAYER IS ENTITLED TO SEE.

;FIRST, PARSE THE COMMAND AND VERIFY THE LEVEL. THE DEFAULT LEVEL NUMBER TO PLOT
;IS THE LEVEL IN WHICH THE PLAYER IS. TO BE IN A LEVEL REQUIRES THAT THE USER IS
;ACTUALLY A PLAYER. THEREFORE, WE REQUIRE THE PLAY COMMAND TO HAVE BEEN
;PREVIOUSLY TYPED. THIS NECESSARILY PRECLUDES A PLAYER FROM GETTING A PLOT
;WITHOUT ACTUALLY PLAYING.


CMDPLT:	NOISE	(ROOMS ON LEVEL);GIVE PLAYER SOME HELP
	HRROI	T1,DEFBUF	;BUILD DEFAULT STRING FOR LEVEL PLAYER IS IN
	MOVE	T2,R.LEVL(R)	;  ..
	MOVX	T3,^D10		;  ..
	NOUT			;  ..
	  JFCL			;BETTER NOT FAIL
	MOVEI	T1,CMDBLK	;RESET COMND STATE BLOCK
	CMMD	DEFBLK		;PARSE DECIMAL LEVEL NUMBER
	MOVE	PL,T2		;SAVE SPECIFIED LEVEL NUMBER
	CONFRM			;END THE LINE
	SKIPL	PL		;RANGE CHECK FOR VALID LEVEL
	CAMLE	PL,H.LEVL	;  ..
	 ERROR	(,,There aren't that many levels in the dungeon.)

;  ..
;  ..

;THE CRITICAL REGION CONSISTS OF TWO PASSES OVER THE ROOMS IN THE CAVE. THE
;FIRST DETERMINES THE MINIMUM AND MAXIMUM X AND Y COORDINATES OF THE ROOMS TO BE
;PLOTTED. FROM THIS, THE SCALE FACTORS USED TO KEEP THE PLOT WITHIN THE BOUNDS
;OF THE PAPER ARE COMPUTED. THEN, THE SECOND PASS PLOTS EACH ROOM AND ITS DOORS.
;LOCKING THE CAVE AROUND BOTH PASSES PREVENTS MORE VALID ROOMS FROM SHOWING UP
;IN THE SECOND PASS, AND POSSIBLY EXCEEDING THE PAPER BOUNDARIES.


	CALL	FAULT		;DRAG IN ALL ROOMS FOR SPEED WHILE LOCKED
	CALL	LOCK		;LOCK UP THE CAVE FOR THE DURATION
	DMOVE	T1,[EXP SCLFST,SCLRST]	;SET UP PROCESSING ROUTINES
	DMOVEM	T1,RMGENS	;  ..
	CALL	GENRMS		;GENERATE VALID ROOMS, CALLING PROCESSING RTNS
	 ERROR	(,,You haven't visited any rooms on that level.)	;NONE
	CALL	PLTSCL		;COMPUTE SCALE FACTOR
	DMOVE	T1,[EXP PLTFST,PLTRST]	;SET UP PLOT PROCESSING ROUTINES
	DMOVEM	T1,RMGENS	;  ..
	SETZM	PLTNUM		;INITIALIZE NUMBER OF ROOMS BEING PLOTTED
	CALL	GENRMS		;GENERATE VALID ROOMS, PLOTTING THIS TIME
	  FATAL	(First pass of plot found rooms but second pass didn't.)
	MOVE	T1,XMAX		;PLOT TO LOWER RIGHT CORNER OF PLOT
	MOVE	T2,YMIN		;  ..
	SETZ	T3,		;  ..
	CALL	PLOT		;  ..
	CALL	PLTCLS		;CLOSE THE PLOTTER FILE
	CALL	UNLOCK		;DONE WITH THE CAVE
	STROUT	[ASCIZ/
The plot contains /]		;TYPE SOME
	DECOUT	PLTNUM		;SAY HOW MANY ROOMS
	STROUT	[ASCIZ/ room/]	;TYPE MORE
	MOVEI	C,"s"		;GET AN S
	SOSE	PLTNUM		;ONLY 1 ROOM?
	PUTCHR			;NOPE, SO MAKE IT PLURAL
	STROUT	[ASCIZ/.
/]				;FINISH
	RET			;DONE COMPLETELY



DEFBLK:	<FLD .CMNUM,CM%FNC>!CM%HPP!CM%DPP ;FUNCTION BLOCK FOR DEFAULT LEVEL NUMBER
	^D10			;DECIMAL RADIX
	POINT 7,[ASCIZ /level of rooms to plot,/]
	POINT 7,DEFBUF		;DEFAULT STRING (SET TO PLAYER'S LEVEL)
;GENRMS GENERATES ALL ROOMS THAT THE CURRENT PLAYER HAS BEEN TO SO FAR, AND
;CALLS ONE OF TWO ROUTINES WITH EACH ROOM.
;
;CALL:
;	RMGENS+0/	ADDR OF ROUTINE FOR FIRST ROOM
;	RMGENS+1/	ADDR OF ROUTINE FOR REST OF ROOMS
;	PL/		LEVEL OF INTEREST
;
;CALLS THE TWO ROUTINES WITH PR POINTING TO THE CURRENT ROOM. GENRMS GIVES
;A NON-SKIP RETURN IF THERE ARE NO MATCHING ROOMS (HAVING CALLED NEITHER
;ROUTINE), A SKIP RETURN OTHERWISE.


GENRMS:	MOVEI	PR,ROMADR-ROMSIZ;START WITH THE FIRST ROOM
	CALL	GETROM		;GET FIRST MATCHING ROOM
	  RET			;NONE THERE
	CALL	@RMGENS+0	;CALL FIRST ROOM ROUTINE
GENRM1:	CALL GETROM		;GET NEXT MATCHING ROOM
	  JRST	CPOPJ1		;DONE
	CALL	@RMGENS+1	;CALL REST OF ROOMS ROUTINE
	JRST	GENRM1		;LOOP UNTIL NO MORE ROOMS



;GETROM SCANS FOR THE NEXT ROOM THAT IS ON THE LEVEL SPECIFIED IN PL, AND
;HAS BEEN VISITED BY THE PLAYER. GIVES NON-SKIP IF NO FURTHER ROOMS MATCH
;THESE CRITERIA, SKIP RETURN WITH PR POINTING TO THE ROOM IF SO.


GETROM:	ADDI	PR,ROMSIZ	;ADVANCE TO NEXT ROOM
	MOVE	T1,H.ROOM	;SEE IF WE'VE SCANNED ALL ROOMS YET
	IMULI	T1,ROMSIZ	;  ..
	CAIL	PR,ROMADR(T1)	;  ..
	RET			;YES--NO MORE ROOMS
	CALL	CHKROM		;ALLOWED TO LOOK AT THIS ROOM?
	  JRST	GETROM		;NO--LOOP FOR NEXT
	JRST	CPOPJ1		;YES--RETURN AS CURRENT ROOM


;ALWROM GIVES A SKIP RETURN IF THE PLAYER IS ACTUALLY ALLOWED TO SEE THE CURRENT
;ROOM, REGARDLESS OF WHETHER THE ROOM WILL BE DRAWN IN THIS PLOT. CHKROM FURTHER
;RESTRICTS THE CHECK TO ROOMS THAT WILL ACTUALLY BE DRAWN.


CHKROM:	CAME	PL,R.LEVL(PR)	;IS THIS ROOM ON THE PROPER LEVEL?
	RET			;NO--TRY NEXT ROOM
ALWROM:	MOVEI	T1,R.VISF(PR)	;HAS PLAYER BEEN HERE BEFORE?
	CALL	BITSET		;  ..
	TDNE	T2,(T1)		;  ..
	JRST	CPOPJ1		;YES--THEN THIS IS A GOOD ROOM
	TXNN	F,FR.DEB	;DEBUGGING?
	RET			;NO--DON'T ALLOW THIS ROOM
	JRST	CPOPJ1		;YES--ALLOW ALL ROOMS ON THIS LEVEL
;SCLFST IS THE SCALING ROUTINE TO CALL WHEN THE FIRST MATCHING ROOM IS FOUND
;BY GENRMS. SIMPLY REMEMBER THE COORDINATES OF THIS ROOM.

SCLFST:	MOVE	T1,R.LOC(PR)	;GET LOCATION OF FIRST MATCHING ROOM
	HLRZM	T1,XMIN		;SET XMIN
	HLRZM	T1,XMAX		;  AND XAMX
	HRRZM	T1,YMIN		;SET YMIN
	HRRZM	T1,YMAX		;  AND YMAX
	RET			;DONE


;SCLRST IS THE SCALING ROUTINE TO CALL FOR ALL OF THE REST OF THE ROOMS. THE
;COORDINATES OF THE CURRENT ROOM IS COMPARED WITH THE X AND Y MAXIMA AND MINIMA,
;EXPANDING THE RANGES IF NECESSARY. WHEN ALL ROOMS HAVE BEEN SEARCHED, THIS
;LEAVES THE BOUNDS OF THE PORTION OF THE CAVE TO BE PLOTTED IN ?MIN AND ?MAX.

SCLRST:	HLRZ	T1,R.LOC(PR)	;RECOMPUTE X BOUNDS
	CAMGE	T1,XMIN		;  XMIN
	MOVEM	T1,XMIN		;  ..
	CAMLE	T1,XMAX		;  XMAX
	MOVEM	T1,XMAX		;  ..
	HRRZ	T1,R.LOC(PR)	;RECOMPUTE Y BOUNDS
	CAMGE	T1,YMIN		;  YMIN
	MOVEM	T1,YMIN		;  ..
	CAMLE	T1,YMAX		;  YMAX
	MOVEM	T1,YMAX		;  ..
	RET			;DONE


;PLTSCL IS CALLED AFTER THE FIRST PASS OVER THE ROOMS TO DETERMINE THE SCALE
;FACTOR FOR THE PLOT. THERE ARE TWO SPECIAL NOTES. FIRST, THE BOUNDS OF THE PLOT
;ARE INCREASED BY THE MAXIMUM POSSIBLE LENGTH OF A DOOR SO THAT DOORS LEADING
;FROM ROOMS AT THE EDGE OF THE PLOT WILL NOT EXCEED THE PAPER. SECOND, A SCALE
;FACTOR LARGER THAN 1.0 IS DECREASED TO 1.0 TO KEEP SMALL LEVELS FROM LOOKING
;REALLY GROSS.

PLTSCL:	FLTR	T3,[SFPMAX+CONMAX] ;COMPUTE MAX DOOR LENGTH - HALF ROOM SIZE
	FSBRI	T3,(0.5)	;  ..
	FLTR	T1,XMIN		;FLOAT AND ADJUST X BOUNDS
	FLTR	T2,XMAX		;  ..
	FSBR	T1,T3		;  ..
	FADR	T2,T3		;  ..
	DMOVEM	T1,XMIN		;SAVE BACK AS MINS AND MAXES
	FLTR	T1,YMIN		;FLOAT AND ADJUST Y BOUNDS
	FLTR	T2,YMAX		;  ..
	FSBR	T1,T3		;  ..
	FADR	T2,T3		;  ..
	DMOVEM	T1,YMIN		;SAVE BACK AS MINS AND MAXES
	FSBR	T2,T1		;COMPUTE RANGE OF Y'S
	MOVX	T1,FWIDTH	;NOW SCALE EVERYTHING TO FIT ON THE PAPER
	FDVR	T1,T2		;T1 = SCALE FACTOR FOR PLOTTING
	CAMLE	T1,[1.0]	;PREVENT PLOTTING HUGE ROOMS
	MOVX	T1,1.0		;  ..
	MOVEM	T1,SCALE	;SAVE AS SCALE FACTOR
	RET			;DONE SCALING
;PLTFST IS THE PLOTTING ROUTINE TO CALL WITH THE FIRST MATCHING ROOM. THE
;PLOTTER IS INITIALIZED, AND THEN THE FIRST ROOM IS PLOTTED.


PLTFST:	CALL	PLTINI		;INITIALIZE THE PLOTTER
;	JRST	PLTRST		;THEN SIMPLY PLOT THE FIRST ROOM


;PLTRST IS THE PLOTTING ROUTINE TO CALL FOR THE REST OF THE ROOMS. PLOT THE ROOM
;OUTLINE (A SQUARE BOX), THE ROOM NUMBER, AND ALL VISIBLE DOORS.


PLTRST:	CALL	PLTSET		;SET UP THIS ROOM'S COORDINATES
	MOVSI	I,-4		;LOOP OVER ALL DIRECTIONS
PLTRS1:	CALL	PLTWAL		;PLOT A WALL IN THE CURRENT DIRECTION
	MOVEI	T1,R.DIRS(PR)	;SET UP ADDRESS OF LINK WORD FOR THIS DIRECTION
	ADDI	T1,(I)		;  FOR SPEED LATER
	MOVEM	T1,MOVLNK	;  ..
	LDB	T1,[POINTR @MOVLNK,DR%TYP] ;GET DOOR TYPE
	CALL	@PLTDOR(T1)	;DRAW THE PROPER DOOR
	AOBJN	I,PLTRS1	;LOOP FOR NEXT DIRECTION, IF ANY LEFT
	AOS	PLTNUM		;ONE MORE ROOM PLOTTED
	RET			;DONE


PLTWAL:	DMOVE	T1,[EXP 0.5,0.5];DRAW ONE WALL OF A UNIT BOX
	MOVX	T3,0		;  ..
	CALL	@PLTDIR(I)	;  ..
	DMOVE	T1,[EXP 0.5,-0.5] ;  ..
	MOVX	T3,1		;  ..
	CALLRET	@PLTDIR(I)	;  ..


PLTSET:	HLRZ	T1,R.LOC(PR)	;COMPUTE X AND Y CENTER COORDINATES
	HRRZ	T2,R.LOC(PR)	;  ..
	FLTR	T1,T1		;  ..
	FLTR	T2,T2		;  ..
	DMOVEM	T1,X		;SAVE FOR EASY REFERENCE
	RET			;DONE (FOR NOW)
	SUBTTL	PLOT (LEVEL) LEVEL-NUMBER -- DOOR SELECTION ROUTINES


;PLTDOR IS A TABLE OF ROUTINE ADDRESSES INDEXED BY DOOR TYPE. EACH ROUTINE IS
;RESPONSIBLE FOR FIGURING OUT WHETHER A DOOR IS ALLOWED TO BE SHOWN FOR THIS
;PLAYER, AND IF SO, FOR PLOTTING THE DOOR.


PLTDOR:	PLTUNK		;UNKNOWN DOOR (USUALLY A BUG)
	PLTNEV		;NON-EXISTENT DOOR
	PLTALW		;USUAL DOOR
	PLTSRC		;SECRET (HIDDEN) DOOR
	PLTLVL		;LEVEL DOOR
	PLTWRD		;MAGIC WORD DOOR
	PLTMAG		;MAGIC ITEM DOOR
	PLTBLK		;BLOCKED (CAVED-IN) DOOR


PLTUNK:	RET			;BUG DOOR. MAYBE SHOW FOR DEBUGGING SOME DAY


PLTNEV:	RET			;NO DOOR--DONE


;HERE TO PLOT A REGULAR DOOR. THERE ARE SEVERAL CASES. IF THERE IS NO CONNECTING
;ROOM, OR THE PLAYER IS NOT ENTITLED TO SEE THE CONNECTING ROOM, THEN WE SIMPLY
;INDICATE THAT THERE IS A DOOR, BUT NOT WHERE IT GOES. OTHERWISE, WE DRAW THE
;COMPLETE DOOR, EVEN IF THE CONNECTING ROOM WILL NOT BE DRAWN (THIS ALLOWS
;PLAYERS TO PLOT PIECES OF LEVELS AND TAPE THE PLOTS TOGETHER TO GET A GOOD
;SCALE FACTOR).

PLTALW:	HRRZ	T1,@MOVLNK	;IS THERE A CONNECTING ROOM?
	CAIN	T1,-1		;  ..
	CALLRET	PLTST1		;NO--DRAW STUB DOOR
	PUSH	P,PR		;YES--RELOCATE TO THE CONNECTING ROOM
	PUSH	P,X		;  ..
	PUSH	P,Y		;  ..
	IMULI	T1,ROMSIZ	;  ..
	MOVEI	PR,ROMADR(T1)	;  ..
	XORI	I,1		;  (REMEMBER TO TURN DIRECTION AROUND)
	CALL	PLTSET		;COMPUTE NEW COORDINATES OF THIS ROOM
	CALL	ALWROM		;ALLOWED TO VIEW THIS ROOM?
	  CALLRET PLTSTB	;NO--DRAW STUB DOOR
	CALL	CHKROM		;ARE WE GOING TO PLOT THE CONNECTING ROOM?
	  JRST	PLTAL1		;NO--THEN DRAW THE DOOR
	CAML	PR,-2(P)	;YES--THEN ONLY DRAW THE DOOR IN ONE DIRECTION
	JRST	[CALL PLTBAK	;WE WILL DRAW (OR HAVE DRAWN) DOOR
		 RET]		;  ..
PLTAL1:	DMOVE	T1,[EXP 0.5,0.0];WE CAN SHOW THE DOOR--START AT
	MOVX	T3,0		;  CONNECTING ROOM AND DRAW A DOOR
	CALL	@PLTDIR(I)	;  FROM THE PROPER WALL TO THE PROPER
	CALL	PLTBAK		;  WALL IN THE ORIGINAL ROOM
	DMOVE	T1,[EXP 0.5,0.0];  ..
	MOVX	T3,1		;  ..
	CALLRET	@PLTDIR(I)	;  ..
;HERE TO PLOT A STUBBY DOOR. THIS REFLECTS THE FACT THAT A PLAYER KNOWS THAT
;THERE IS A DOOR, BUT DOES NOT KNOW WHERE IT GOES. THIS OCCURS, FOR INSTANCE, IF
;THE PLAYER CAN SEE THE DOOR IN THE CURRENT ROOM, BUT IS NOT ALLOWED TO SEE (HAS
;NOT VISITED) THE CONNECTING ROOM.


PLTSTB:	CALL	PLTBAK		;GET BACK TO ORIGINAL ROOM
PLTST1:	DMOVE	T1,[EXP 0.5,0.0];DRAW JUST A SHORT (STUBBY) LINE
	MOVX	T3,0		;  ..
	CALL	@PLTDIR(I)	;  ..
	DMOVE	T1,[EXP 1.0,0.0];  ..
	MOVX	T3,1		;  ..
	CALLRET	@PLTDIR(I)	;  ..


;HERE TO PLOT A SECRET DOOR. WE DETERMINE WHETHER TO DRAW NOTHING, A STUB DOOR,
;OR A REAL DOOR BY EITHER PLOTTING NOTHING, OR REDUCING THE PROBLEM TO A REGULAR
;DOOR.


PLTSRC:	MOVEI	T1,R.SRCF(PR)	;HAS PLAYER SEARCHED HERE?
	CALL	BITSET		;  ..
	TDNE	T2,(T1)		;  ..
	CALLRET	PLTALW		;YES--THEN JUST LIKE A REGULAR DOOR
	HRRZ	T1,@MOVLNK	;NO--SEE IF SEARCHED IN CONNECTING ROOM
	CAIN	T1,-1		;  (SEARCHED THERE IMPLIES VISITED THERE TOO)
	RET			;  (NO CONNECTING ROOM--SHOW NOTHING)
	IMULI	T1,ROMSIZ	;  ..
	ADDI	T1,ROMADR+R.SRCF;  ..
	CALL	BITSET		;  ..
	TDNN	T2,(T1)		;  ..
	RET			;NOT VISIBLE THERE EITHER--SHOW NOTHING
	CALLRET PLTALW		;VISIBLE THERE--TREAT AS USUAL DOOR


;HERE TO PLOT A LEVEL-CHANGE DOOR. SINCE WE ARE ONLY CONCERNED WITH ROOMS ON THE
;CURRENT LEVEL, WE MERELY INDICATE THE LEVEL CHANGE WITH AN ARROW.


PLTLVL:	DMOVE	T1,[EXP 0.5,0.5] ;DRAW AN ARROW TO INDICATE LEVEL CHANGE
	MOVX	T3,0		;  ..
	CALL	@PLTDIR(I)	;  ..
	DMOVE	T1,[EXP 1.0,0.0];  ..
	MOVX	T3,1		;  ..
	CALL	@PLTDIR(I)	;  ..
	DMOVE	T1,[EXP 0.5,-0.5] ;  ..
	MOVX	T3,1		;  ..
	CALLRET	@PLTDIR(I)	;  ..
PLTWRD:	RET			;FOR NOW


PLTMAG:	RET			;FOR NOW


;HERE TO PLOT A CAVED-IN (BLOCKED) DOOR. THIS LOOKS LIKE A STUBBY DOOR WITH AN
;EXTRA LINE INDICATING THE BLOCKAGE.


PLTBLK:	DMOVE	T1,[EXP 0.5,0.0];PLOT A CAVED-IN DOOR
	MOVX	T3,0		;  ..
	CALL	@PLTDIR(I)	;  ROTATING IT TO PROPER DIRECTION
	DMOVE	T1,[EXP 1.0,0.0];  ..
	MOVX	T3,1		;  ..
	CALL	@PLTDIR(I)	;  ..
	DMOVE	T1,[EXP 1.0,.25];  ..
	MOVX	T3,0		;  ..
	CALL	@PLTDIR(I)	;  ..
	DMOVE	T1,[EXP 1.0,-0.25] ;  ..
	MOVX	T3,1		;  ..
	CALLRET	@PLTDIR(I)	;  ..


;PLTBAK IS USED AFTER RELOCATING TO THE CONNECTING ROOM, TO GET BACK TO THE
;ORIGINAL ROOM.


PLTBAK:	POP	P,T1		;SAVE RETURN ADDRESS
	POP	P,Y		;RESTORE ROOM PARAMETERS
	POP	P,X		;  ..
	POP	P,PR		;  ..
	XORI	I,1		;  (TURN DOOR AROUND)
	JRST	(T1)		;DONE
	SUBTTL	PLOT (LEVEL) LEVEL-NUMBER -- DOOR ROTATION ROUTINES


;PLTDIR IS A TABLE OF ROUTINE ADDRESSES INDEXED BY DIRECTION (EAST, NORTH, SOUTH
;OR WEST). EACH ROUTINE HAS THE SAME ARGUMENTS AS PLOT, EXCEPT THAT THE X AND Y
;COORDINATES ARE RELATIVE TO THE CENTER OF THE ROOM BEING PLOTTED, AND THAT
;WHATEVER IS BEING PLOTTED IS IN THE EAST DIRECTION. EACH ROUTINE THEN ROTATES
;THE COORDINATES TO THE PROPER DIRECTION, AND ADDS IN THE CENTER COORDINATES OF
;THE CURRENT ROOM.


PLTDIR:	PLOT.N		;ROTATE TO NORTH
	PLOT.S		;ROTATE TO SOUTH
	PLOT.E		;ROTATE TO EAST (NOT MUCH WORK)
	PLOT.W		;ROTATE TO WEST


PLOT.E:	FADR	T1,X		;ALREADY ROTATED--OFFSET TO CURRENT ROOM
	FADR	T2,Y		;  ..
	CALLRET	PLOT		;PLOT THE POINT


PLOT.N:	EXCH	T1,T2		;ROTATE TO NORTH
	MOVNS	T1		;  ..
	FADR	T1,X		;OFFSET TO CURRENT ROOM
	FADR	T2,Y		;  ..
	CALLRET	PLOT		;PLOT THE POINT


PLOT.S:	EXCH	T1,T2		;ROTATE TO SOUTH
	MOVNS	T2		;  ..
	FADR	T1,X		;OFFSET TO CURRENT ROOM
	FADR	T2,Y		;  ..
	CALLRET	PLOT		;PLOT THE POINT


PLOT.W:	MOVNS	T1		;ROTATE TO WEST
	MOVNS	T2		;  ..
	FADR	T1,X		;OFFSET TO CURRENT ROOM
	FADR	T2,Y		;  ..
	CALLRET	PLOT		;PLOT THE POINT
	SUBTTL	BASIC PLOTTING ROUTINES


;PLOT IS THE LOW-LEVEL PLOTTING ROUTINE FOR DRAWING LINES. PLTINI SHOULD BE
;CALLED PRIOR TO ANY PLOTTING, THEN  THE CALL IS:
;
;	T1/	X COORDINATE
;	T2/	Y COORDINATE
;	T3/	PEN POSITION (0 FOR UP, 1 FOR DOWN)
;	XMIN/	LOWEST POSSIBLE X COORDINATE (FOR SCALING)
;	YMIN/	LOWEST POSSIBLE Y COORDINATE (FOR SCALING)
;	SCALE/	MULTIPLICATIVE SCALE FACTOR
;
;THE TWO COORDINATES SHOULD BE SINGLE-PRECISION FLOATING-POINT NUMBERS, AND
;REPRESENT THE COORDINATE TO PLOT TO. BOTH ARE SCALED THROUGH CAVE'S INTERNAL
;SCALE FACTORS TO FIT THE PLOT ON THE PAPER.
;
;THE ALGORITHM USED IS BASICALLY THE FOLLOWING:
;
;  1.	SEE IF THE REQUESTED STATE OF THE PEN IS DIFFERENT FROM ITS CURRENT
;	STATE, AND IF SO, CHANGE IT.
;  2.	SCALE THE X AND Y COORDINATES TO FIT IN THE BOUNDS OF THE PLOTTING
;	PAPER, THEN CONVERT TO PAPER INCREMENT COORDINATES.
;  3.	DETERMINE THE (AT MOST) TWO INCREMENTS TO BE USED TO DRAW THE LINE. THIS
;	WILL ALWAYS BE AN ON-AXIS INCREMENT AND (POSSIBLY) A COMBINED INCREMENT
;	(E.G., +X+Y).
;  4.	LOOP ALONG THE MAJOR AXIS (THE ONE WITH THE MAXIMUM ABSOLUTE COORDINATE
;	OF THE VECTOR REPRESENTING OUR MOTION), SELECTING THE PROPER OF THE TWO
;	INCREMENTS.
;
;THIS IS ESSENTIALLY THE SAME ALGORITHM AS THE ONE USED BY FOROTS, EXCEPT THAT
;YOU GET COMMENTS.
PLOT:	CAMN	T3,OLDPEN	;DO WE NEED A PEN CHANGE?
	JRST	PLOT1		;NO--DON'T BOTHER
	MOVEM	T3,OLDPEN	;YES--REMEMBER NEW PEN STATE
	PUSH	P,T2		;SAVE Y
	MOVE	T2,[EXP XY%UP,XY%DWN](T3) ;GET PLOTTER COMMAND FOR PEN STATE
	CALL	PUTPLT		;SEND THE COMMAND
	POP	P,T2		;RESTORE Y
PLOT1:	FSBR	T1,XMIN		;SCALE X TO FIT THE PAPER
	FMPR	T1,SCALE	;  ..
	FMPRI	T1,(FSTEPS)	;TURN INTO PLOTTER INCREMENTS
	FIXR	T1,T1		;ROUND TO NEAREST INTEGER
	FSBR	T2,YMIN		;SCALE Y TO FIT THE PAPER
	FMPR	T2,SCALE	;  ..
	FMPRI	T2,(FSTEPS)	;TURN INTO PLOTTER INCREMENTS
	FIXR	T2,T2		;ROUND TO NEAREST INTEGER
	SUB	T1,OLDIX	;COMPUTE X VECTOR COMPONENT
	ADDM	T1,OLDIX	;  AND SAVE NEW LOCATION AS OLD
	SUB	T2,OLDIY	;COMPUTE Y VECTOR COMPONENT
	ADDM	T2,OLDIY	;  AND SAVE NEW LOCATION AS OLD
	MOVX	T3,XY%MX	;ASSUME WE'LL USE -X INCREMENTS
	SKIPL	T1		;SEE IF SO
	MOVX	T3,XY%PX	;NO--WE'LL USE +X INCREMENTS
	MOVX	T4,XY%MY	;ASSUME WE'LL USE -Y INCREMENTS
	SKIPL	T2		;SEE IF SO
	MOVX	T4,XY%PY	;NO--WE'LL USE +Y INCREMENTS
	MOVMS	T1		;COMPUTE MAXIMUM ABSOLUTE COMPONENT OF VECTOR
	MOVMS	T2		;  WHICH DETERMINES MAJOR AXIS
	CAMG	T2,T1		;  AND PUT IT AND ITS INCREMENT FIRST
	JRST	PLOT2		;  ..
	EXCH	T1,T2		;  ..
	EXCH	T3,T4		;  ..
PLOT2:	OR	T4,T3		;USE COMBINED INCREMENT AND ONE ASSOCIATED
				;  WITH MAJOR AXIS
	DMOVEM	T3,TWODIR	;SAVE THE INCREMENTS FOR LATER
	JUMPE	T1,PLOTDN	;DONE IF MAJOR AXIS COMPONENT = 0 (BOTH = 0)
	JUMPN	T2,PLOT3	;IF MINOR AXIS COMPONENT = 0
	SETZM	MININC		;THEN NO INCREMENT TO MINOR AXIS PER UNIT
	JRST	PLOT4		;  MAJOR AXIS INCREMENT
PLOT3:	FLTR	T3,T1		;ELSE COMPUTE INCREMENT TO MINOR AXIS PER
	FLTR	T4,T2		;  UNIT MAJOR AXIS INCREMENT
	FDVR	T4,T3		;  WHICH IS SLOPE, SORT OF
	MOVEM	T4,MININC	;  ..
PLOT4:	DMOVE	T3,T1		;PUT AXIS COUNTERS IN SAFE ACS
	MOVX	T1,0.5		;INITIALIZE MINOR AXIS COUNTER
PLOT5:	FADR	T1,MININC	;SEE HOW FAR WE GO IN MINOR DIRECTION
	MOVE	T2,TWODIR+0	;ASSUME WE ONLY INCREMENT MAJOR AXIS
	CAML	T1,[1.0]	;SEE IF SO
	JRST	[FSBRI T1,(1.0)		;NO, WE INCREMENT BOTH THIS TIME
		 MOVE T2,TWODIR+1	;  SO SET UP COMBINED INCREMENT
		 SOJA T4,.+1]		;  AND ACCOUNT FOR MINOR AXIS
	CALL	PUTPLT		;MOVE THE PLOTTER
	SOJG	T3,PLOT5	;COUNT ANOTHER MAJOR AXIS INCREMENT
PLOTDN:	RET			;DONE WITH THIS LINE
;PLTINI INITIALIZES THE PLOTTER FILE BY OPENING IT UP, MAKING SURE IT'S REALLY
;A DISK, AND THEN SMASHING THE PEN INTO THE RIGHT SIDE OF THE PAPER TO ASSURE
;WE'RE ON THE RIGHT MARGIN.


PLTINI:	MOVX	T1,GJ%SHT!GJ%FOU;GET A NEW FILE
	HRROI	T2,[ASCIZ /CAVE.PLT/] ;  ..
	GTJFN			;  ..
	  ERJMP	PLTIN1		;CAN'T--GO UNLOCK AND BOMB OUT
	HRRZM	T1,PJFN		;SAVE JFN FOR LATER
	DVCHR			;SEE WHAT KIND OF DEVICE WE HAVE
	LDB	T1,[POINTR T2,DV%TYP] ;  ..
	CAIE	T1,.DVDSK	;MUST BE A DISK
	 ERROR	(,,Output can only go to a disk.)	;OTHERWISE YELL
	MOVE	T1,PJFN		;NOW OPEN THE FILE
	MOVX	T2,<<FLD 6,OF%BSZ>!OF%WR> ;  ..
	OPENF			;  ..
	  ERJMP	PLTIN1		;CAN'T--GO UNLOCK AND BOMB OUT
	MOVX	T1,6*PAGSIZ	;INITIALIZE BUFFER COUNTS
	MOVEM	T1,PLTCNT	;  ..
	SETZM	PLTTOT		;  ..
	MOVE	T1,[POINT 6,PLTADR] ;INITIALIZE BUFFER BYTE POINTER
	MOVEM	T1,PLTPTR	;  ..
	HRLZ	T1,PJFN		;INITIALIZE PAGE COUNTER
	SUBI	T1,1		;  SO AOS WILL WORK (OVERFLOW PROPERLY)
	MOVEM	T1,PLTPGN	;  ..
	MOVX	T2,XY%UP	;START BY RAISING THE PEN
	CALL	PUTPLT		;  ..
	SETZM	OLDPEN		;REMEMBER IT'S NOW RAISED
	MOVSI	T3,-IWIDTH*ISTEPS ;SMASH INTO EDGE OF PAPER
	MOVX	T2,XY%MY	;  ..
	CALL	PUTPLT		;  ..
	AOBJN	T3,.-1		;  ..
	MOVSI	T3,-ISTEPS/2	;COME BACK OUT 1/2 INCH
	MOVX	T2,XY%PY	;  ..
	CALL	PUTPLT		;  ..
	AOBJN	T3,.-1		;  ..
	SETZM	OLDIX		;NOW WE'RE AT 0,0
	SETZM	OLDIY		;  ..
	RET			;DONE INITIALIZING THE PLOTTER


PLTIN1:	HRROI	T3,[ASCIZ /Can't initialize plotter file, /]
	JRST	JSFAIL		;UNLOCK CAVE AND PRINT REASON
;PLTCLS CLOSES THE PLOTTER FILE AT THE END OF THE PLOT, OR IF AN OUTPUT ERROR
;OCCURS. SINCE PMAP%'S WERE USED TO WRITE THE FILE, WE MUST SET THE END-OF-FILE
;POINTER MANUALLY. PLTTOT CONTAINS THE TOTAL NUMBER OF BYTES WRITTEN THROUGH THE
;LAST COMPLETE PAGE, AND PLTCNT ACCOUNTS FOR THE REST.


PLTCLS:	SKIPN	PLTCNT		;ANYTHING TO OUTPUT?
	JRST	PLTCLS1		;NO--DON'T OUTPUT ANYTHING
	MOVE	T1,[.FHSLF,,PLTPAG] ;WRITE LAST OUTPUT BUFFER
	AOS	T2,PLTPGN	;  TO PLOTTER FILE
	MOVX	T3,PM%RWX!PM%CNT+1 ;  ..
	SETZM	PLTCNT		;PREVENT LOOPS IF LAST PAGE GETS ERROR
	PMAP			;  ..
	  ERJMP	PUTPL2		;NO LUCK--UNLOCK THE CAVE AND BOMB OUT
	MOVX	T1,<CF%NUD!<FLD .FBBYV,CF%DSP>> ;SET END-OF-FILE POINTER
	HRR	T1,PJFN		;  ..
	MOVX	T2,FB%BSZ	;  FIRST BYTE SIZE
	MOVX	T3,<FLD 6,FB%BSZ> ;  ..
	CHFDB			;  ..
	MOVX	T1,<CF%NUD!<FLD .FBSIZ,CF%DSP>> ;  NOW BYTE COUNT
	HRR	T1,PJFN		;  ..
	SETO	T2,		;  ..
	MOVE	T3,PLTTOT	;  ..
	ADDI	T3,6*1000	;    COUNT A PARTIAL PAGE
	SUB	T3,PLTCNT	;    ..
	CHFDB			;  ..
	MOVE	T1,PJFN		;CLOSE THE FILE
	CLOSF			;  ..
	  ERJMP	.		;DON'T CARE
	RET			;DONE
;PUTPLT WRITES THE PEN COMMANDS TO THE PLOTTER FILE. THE CALL IS:
;
;	T2/	PLOTTER COMMAND
;
;SAVES ALL ACS, DOES NOT RETURN ON ERRORS.


PUTPLT:	SOSGE	PLTCNT		;ROOM FOR ANOTHER PEN COMMAND?
	JRST	PUTPL1		;NO--WRITE CURRENT PAGE AND GET NEW ONE
	IDPB	T2,PLTPTR	;YES--WRITE BYTE
	RET			;DONE

PUTPL1:	PUSH	P,T1		;SAVE SOME ACS FOR PMAP
	PUSH	P,T2		;  ..
	PUSH	P,T3		;  ..
	MOVE	T1,[.FHSLF,,PLTPAG] ;WRITE OUTPUT BUFFER
	AOS	T2,PLTPGN	;  TO PLOTTER FILE
	MOVX	T3,PM%RWX!PM%CNT+1 ;  ..
	PMAP			;  ..
	  ERJMP	PUTPL2		;NO LUCK--UNLOCK THE CAVE AND BOMB OUT
	MOVX	T1,6*1000	;RESET BYTE COUNTER
	MOVEM	T1,PLTCNT	;  ..
	ADDM	T1,PLTTOT	;  AND COUNT ANOTHER PAGE OF BYTES IN FILE
	MOVE	T1,[POINT 6,PLTADR] ;RESET BYTE POINTER
	MOVEM	T1,PLTPTR	;  ..
	POP	P,T3		;RESTORE SAVED ACS
	POP	P,T2		;  ..
	POP	P,T1		;  ..
	CALLRET	PUTPLT		;NOW GO WRITE THE PEN COMMAND

PUTPL2:	MOVEI	T3,[ASCIZ /Output error writing plotter file, /]
	MOVX	T1,.FHSLF	;GET THE REASON FOR FAILURE
	GETER			;  ..
	HRRZ	T4,T2		;MAKE ARG FOR JEFAIL
	CALL	PLTCLS		;CLOSE THE PLOTTER FILE
	JRST	JEFAIL		;GO UNLOCK AND PRINT REASON
	SUBTTL	ERROR ROUTINES THAT BOMB THE CURRENT COMMAND


;JSFAIL IS CALLED WHEN A JSYS FAILS WHILE THE CAVE IS LOCKED. THE JSYS ERROR
;CODE IS SAVED, THE CAVE UNLOCKED, AND THEN THE MESSAGE PRINTED. THIS PREVENTS
;THE PLAYER FROM CAUSING THE TERMINAL TO HANG WHILE THE CAVE IS LOCKED. THE CALL IS:
;
;	T3/	POINTER TO FIXED PART OF MESSAGE

JSFAIL:	MOVX	T1,.FHSLF	;GET LAST ERROR CODE
	GETER			;  ..
	HRRZ	T4,T2		;SAVE OVER UNLOCK CALL
;	JRST	JEFAIL		;GO UNLOCK AND PRINT MESSAGES


;JEFAIL IS SIMILAR TO JSFAIL, BUT WHEN THE ERROR CODE IS ALREADY KNOWN. THE CALL IS:
;
;	T3/	POINTER TO FIXED PART OF MESSAGE
;	T4/	SYSTEM ERROR CODE OF REST OF MESSAGE

JEFAIL:	CALL	UNLOCK		;UNLOCK THE CAVE
	HRROI	T1,[ASCIZ /
? /]				;MAKE THIS AN ERROR
	PSOUT			;  ..
	MOVE	T1,T3		;PRINT FIXED PART OF MESSAGE
	PSOUT			;  ..
	MOVX	T1,.PRIOU	;PRINT SYSTEM MESSAGE
	MOVSI	T2,.FHSLF	;  ..
	HRR	T2,T4		;  ..
	SETZ	T3,		;  ..
	ERSTR			;  ..
	  JFCL			;DON'T CARE HERE
	  JFCL			;  ..
	HRROI	T1,[ASCIZ /

/]				;END THE MESSAGE AND ALSO A BLANK LINE
	PSOUT			;  ..
	MOVE	P,SAVEP		;UNWIND STACK TO COMMAND LEVEL
	JRST	GETCMD		;PROCESS A NEW COMMAND
	SUBTTL	FAULT -- PAGE IN ALL ROOMS


;THIS ROUTINE IS CALLED BEFORE LOCKING UP THE FILE IN CASES WHERE ALL
;THE ROOMS OF THE DUNGEON HAVE TO EXAMINED.  THUS OTHER PLAYERS WILL NOT
;BE LOCKED OUT FOR A LONG TIME WHILE WE HAVE THE FILE LOCKED.


FAULT:	MOVE	T1,H.ROOM	;GET HIGHEST ROOM NUMBER
	IMULI	T1,ROMSIZ	;CONVERT TO LAST ADDRESS USED
	ADDI	T1,ROMADR	;  ..

FLTLOP:	SKIP	(T1)		;TOUCH THIS PAGE TO BRING IT IN
	SUBI	T1,PAGSIZ	;BACK DOWN TO PREVIOUS PAGE
	CAIL	T1,MAPADR	;TOUCHED ALL PAGES YET?
	JRST	FLTLOP		;NO, KEEP GOING
	RET			;YES, DONE
	SUBTTL	COMMANDS TO MANIPULATE PATHS




;THE DEFINE COMMAND.  USED TO DEFINE A PATH NAME SO IT CAN BE TAKEN
;LATER.


CMDDEF:	NOISE	(PATH NAME)	;ASK WHAT WE WANT
	CALL	PARPTH		;READ IN A PATH NAME
	SKIPN	T2		;WANTS ALL?
	 ERROR	(,,You cannot define all names!)	;YEP, ILLEGAL
	MOVEM	T2,PTHNAM	;REMEMBER IT FOR AWHILE
	NOISE	(TO BE THE DIRECTIONS)	;MORE NOISE
	CALL	GETPTH		;READ IN LIST OF DIRECTIONS
	CALL	LOCK		;INTERLOCK THE FILE
	MOVE	T1,PTHNAM	;GET NAME OF PATH
	SKIPN	PTHCNT		;ANY DIRECTIONS SPECIFIED?
	JRST	UNPATH		;NO, GO REMOVE IT
	CALL	PTHADD		;DEFINE IT FOR LATER
	 ERROR	(,,Not enough room to store this path.)	;FAILED
	SKIPA			;OK
UNPATH:	CALL	PTHDEL		;DELETE THE PATH
	CALL	UNLOCK		;FREE UP FILE AGAIN
	STROUT	[ASCIZ/
OK.
/]				;SAY WE DID IT
	RET			;DONE
;COMMAND TO DELETE PATH DEFINITIONS.




CMDDEL:	NOISE	(DEFINITION OF PATH)	;GET NOISE
	CALL	PARPTH		;GET IT
	CONFRM			;CONFIRM THE LINE
	CALL	LOCK		;LOCK THE FILE
	SKIPN	T1,T2		;MOVE AND SEE IF WANTS ALL NAMES DELETED
	JRST	DELALL		;YES
	CALL	PTHDEL		;NO, JUST DELETE THE NAMED PATH
	CALL	UNLOCK		;UNLOCK THE FILE
	STROUT	[ASCIZ/
OK.
/]				;DONE
	RET			;RETURN



DELALL:	SETZM	U.PATN(U)	;CAN'T CONTINUE ANY PATH NOW
	SETZM	U.PATI(U)	;NO BYTE POINTER EITHER
	SETZM	U.PATH(U)	;CLEAR BEGINNING OF PATH DEFINITIONS
	SETZM	U.PATH+PTHMAX-1(U)	;AND LAST WORD JUST IN CASE
	CALL	UNLOCK		;UNLOCK
	STROUT	[ASCIZ/
All definitions cleared.
/]				;DONE
	RET			;RETURN
;COMMAND TO TYPE OUT THE DEFINITION OF A PATH.



CMDTYP:	NOISE	(DEFINITION OF PATH NAME)	;NOISE
	CALL	PARPTH		;READ IT IN
	MOVEM	T2,PTHNAM	;SAVE IT FOR AWHILE
	CONFRM			;CONFIRM THE LINE
	CALL	LOCK		;LOCK UP THE FILE
	SKIPN	T1,PTHNAM	;GET PATH NAME AND SEE IF ALL WANTED
	JRST	TYPALL		;YES, TYPE THEM ALL
	CALL	PTHSRC		;LOOK FOR THE NAME
	 ERROR	(,,There is no such path defined.)	;FAILED
	HLRZ	T2,1(T1)	;GET LENGTH OF DATA
	ADDI	T2,MOVLST	;GET LAST WORD TO BLT TO
	HRLZ	T1,T1		;PUT ADDRESS IN LEFT HALF
	HRRI	T1,MOVLST	;AND PLACE TO BLT TO
	BLT	T1,(T2)		;MOVE TO SAFE PLACE
	CALL	UNLOCK		;NOW UNLOCK THE FILE
	DOCRLF			;START WITH A CRLF
	STROUT	[ASCIZ/Path /]	;START OUTPUT
	MOVE	T1,PTHNAM	;GET NAME
	CALL	TTYSIX		;TYPE IT IN SIXBIT
	STROUT	[ASCIZ/ is /]	;MORE OUTPUT
	MOVE	T4,[POINT PTHWID,MOVLST+1,17]	;SET UP POINTER
	TXZ	F,FR.TMP	;INITIALIZE TEMPORARY FLAG.

TYPPTL:	ILDB	T3,T4		;GET NEXT DIRECTION
	CAIN	T3,PTHMSK	;END OF THE LIST?
	JRST	TYPPTF		;YES, GO FINISH
	TXOE	F,FR.TMP	;FIRST DIRECTION?
	STROUT	[ASCIZ/, /]	;NO, SPACE OVER
	STROUT	@DORTXT(T3)	;TYPE DIRECTION
	JRST	TYPPTL		;LOOP

TYPPTF:	STROUT	[ASCIZ/.
/]				;FINISH IT
	RET			;DONE
;HERE TO LIST ALL THE PATHS WE KNOW ABOUT:


TYPALL:	MOVSI	I,-MOVMAX	;GET A COUNTER READY
	MOVEI	T1,U.PATH(U)	;POINT TO FIRST PATH NAME

TYPALN:	CAILE	T1,U.PATH+PTHMAX-2(U)	;MAKE SURE LEGAL
	 ERROR	(,,Path definition format is bad.)
	MOVE	T2,0(T1)	;GET NAME OF PATH
	MOVEM	T2,MOVLST(I)	;SAVE AWAY
	JUMPE	T2,TYPALY	;GO ON IF DONE NOW
	HLRZ	T2,1(T1)	;GET LENGTH
	ADDI	T1,1(T2)	;MOVE TO NEXT NAME
	AOBJN	I,TYPALN	;LOOP
	ERROR	(,,Not enough storage for all path definitions.)

TYPALY:	MOVEI	T4,U.PATH+PTHMAX-1(U)	;GET LAST WORD
	SUB	T4,T1		;REMEMBER HOW MANY FREE WORDS
	CALL	UNLOCK		;UNLOCK FILE
	DOCRLF			;DO A CRLF
	SKIPN	MOVLST		;NO PATH NAMES?
	STROUT	[ASCIZ/No paths are defined.  /]	;YEP
	SKIPN	MOVLST		;WELL?
	JRST	TYPFRE		;NONE, GO SAY WHAT IS FREE
	STROUT	[ASCIZ/Defined paths:  /]	;START OUT
	SETZB	T3,LISOLD	;GET READY FOR LIST OUTPUT

TYPALZ:	SKIPN	MOVLST(T3)	;ALL DONE?
	JRST	TYPALX		;YES
	HRLZ	T1,T3		;GET OFFSET READY
	IORI	T1,[MOVE T1,MOVLST(T1)	;GET ROUTINE TO GET NAME
		    JRST TTYSIX]	;AND OUTPUT IT
	CALL	DOLIST		;ADD TO LIST
	AOJA	T3,TYPALZ	;LOOP

TYPALX:	CALL	DOLISE		;END THE LIST
	STROUT	[ASCIZ/.  /]	;TYPE PERIOD
TYPFRE:	STROUT	[ASCIZ/

Free words:  /]			;GET READY
	DECOUT	T4		;TYPE HOW MANY WORDS ARE FREE
	DOCRLF			;FINISH WITH CRLF
	RET			;DONE
;SUBROUTINE TO PARSE A PATH NAME WHICH IS A SIXBIT QUANTITY.  RETURNS
;PATH NAME IN T2.  IF THE SPECIAL PATH NAME "ALL" IS SPECIFIED, THEN
;ZERO IS RETURNED IN T2.



PARPTH:	CMMD	[FLDDB. (.CMFLD,CM%HPP+CM%SDH,,path name)]	;READ NAME
	SETZ	T2,		;START WITH NULL
	MOVE	T3,[POINT 6,T2]	;GET POINTER TO IT
	MOVE	T4,[POINT 7,ATMBUF]	;POINT TO ATOM BUFFER

PARPTL:	ILDB	C,T4		;GET NEXT CHARACTER
	JUMPE	C,PARPTF	;NO MORE
	TXNN	T3,77B5		;IS WORD FULL ALREADY?
	 ERROR	(,,Path names can only have six characters.)	;YES
	CAIL	C,"A"+40	;LOWER CASE?
	CAILE	C,"Z"+40	;WELL?
	SKIPA			;NO
	SUBI	C,40		;YES, MAKE UPPER CASE
	SUBI	C," "		;CONVERT TO SIXBIT
	IDPB	C,T3		;STORE IT
	JRST	PARPTL		;LOOP

PARPTF:	SKIPN	T2		;VERIFY WE HAVE ONE
	 ERROR	(,,Bad path name specified.)	;NO
	CAMN	T2,[SIXBIT/ALL/]	;IS IT THE SPECIAL "ALL" ONE?
	SETZ	T2,		;YES, CLEAR AC
	RET			;DONE
	SUBTTL	COMMAND TO FOLLOW A PATH




;THIS COMMAND LETS THE USER FOLLOW A PATH WHICH HE HAS PREVIOUSLY
;DEFINED.



CMDFOL:	NOISE	(THE PATH)	;NOISE
	CALL	PARPTH		;READ THE PATH NAME
	SKIPN	T2		;SEE IF SPECIFYING ALL
	 ERROR	(,,You cannot follow all paths!)	;YES, ILLEGAL
	MOVEM	T2,PTHNAM	;SAVE FOR LATER
	CONFRM			;CONFIRM THE LINE
	CALL	TELROB		;MENTION ANY ROBBERIES
	CALL	LOCK		;LOCK UP THE DATA FILE
	MOVE	T1,PTHNAM	;GET BACK NAME
	CALL	PTHSRC		;LOOK FOR IT
	 ERROR	(,,There is no such path defined.)	;NOT FOUND
	SETZM	U.PATN(U)	;CLEAR ANY PREVIOUS PATH
	MOVE	T1,[POINT PTHWID,1,17]	;GET POINTER
	MOVEM	T1,U.PATI(U)	;REMEMBER POINTER INTO LIST
	MOVE	T1,PTHNAM	;GET BACK NAME
	MOVEM	T1,U.PATN(U)	;AND SET IT UP
	MOVE	T1,U.ROOM(U)	;GET CURRENT ROOM
	MOVEM	T1,U.PATR(U)	;AND SET AS ROOM TO PROCEED FROM
	JRST	DOPROC		;GO PROCEED FROM BEGINNING NOW



CMDPRO:	NOISE	(ALONG INTERRUPTED PATH)	;NOISE
	CONFRM			;THEN CONFIRM THE LINE
	CALL	LOCK		;LOCK UP THE FILE
;	JRST	DOPROC		;FALL INTO MAIN CODE
;HERE TO DO THE WORK OF MOVING ALONG A PATH:




DOPROC:	SKIPN	T1,U.PATN(U)	;GET THE PATH NAME
	 ERROR	(,,No path was being followed.)	;NONE, SAY SO
	CALL	PTHSRC		;LOOK FOR THE PATH
	 ERROR	(<SETZM	U.PATN(U)>,,The path to follow got lost!!)
	SKIPN	T2,U.PATI(U)	;GET BYTE POINTER INTO PATH
	 ERROR	(<SETZM U.PATN(U)>,,I don't know where in the path you are!!)
	ADD	T1,T2		;MAKE FINISHED POINTER
	MOVEM	T1,PTHBYT	;SAVE BYTE POINTER FOR LOOP

PROLOP:	MOVE	T4,U.PATR(U)	;GET ROOM WE SHOULD PROCEED FROM
	CAME	T4,U.ROOM(U)	;THE ONE WE ARE IN?
	JRST	PROBAD		;NO, COMPLAIN
	ILDB	T1,PTHBYT	;GET NEXT DIRECTION TO MOVE IN
	CAIN	T1,PTHMSK	;END OF THE PATH?
	JRST	PROFIN		;YES, GO FINISH UP
	CALL	DOMOVE		;TRY TO MOVE AS INDICATED
	 RET			;CANT, RETURN WITH MESSAGE TYPED
	IBP	U.PATI(U)	;DID IT, ADVANCE BYTE POINTER
	MOVE	T1,U.ROOM(U)	;GET NEW ROOM
	MOVEM	T1,U.PATR(U)	;SET AS ROOM TO PROCEED FROM
	MOVE	T1,PTHBYT	;GET READY TO PEEK AHEAD
	ILDB	T1,T1		;TO SEE IF MORE TO DO
	CAIN	T1,PTHMSK	;WAS THAT THE LAST DIRECTION?
	JRST	PROFIN		;YES, STOP NOW
	CALL	NOTICE		;SEE IF WE SEE ANYTHING INTERESTING
	 JRST	PROLOP		;NO, CONTINUE ON
	MOVE	T4,PTHBYT	;GET COPY OF POINTER
	ILDB	T4,T4		;GET NEXT DIRECTION
	CALL	UNLOCK		;UNLOCK FILE
	JRST	INTRST		;GO SAY SOMETHING INTERESTING HERE
PROFIN:	SETZM	U.PATN(U)	;CLEAR PATH BEING FOLLOWED
	SETZM	U.PATI(U)	;AND BYTE POINTER
	SETZM	U.PATR(U)	;AND ROOM
	CALL	UNLOCK		;UNLOCK FILE
	JRST	LOOK		;THEN LOOK AROUND



PROBAD:	CALL	UNLOCK		;UNLOCK THE FILE
	STROUT	[ASCIZ/
To proceed you first have to return to room /]	;START IT
	DECOUT	T4		;SAY WHERE TO RETURN TO
	STROUT	[ASCIZ/.
/]				;FINISH TEXT
	RET			;DONE
	SUBTTL	COMMANDS TO DO MOVEMENT




;HERE FOR THE NORTH, SOUTH, EAST, WEST, AND BACK-UP COMMANDS.



CMDMVN:	SKIPA	T2,[EXP DIR.N]	;GET DIRECTION FOR NORTH
CMDMVS:	MOVEI	T2,DIR.S	;OR FOR SOUTH
	JRST	SAVMOV		;JOIN COMMON CODE

CMDMVE:	SKIPA	T2,[EXP DIR.E]	;GET DIRECTION FOR EAST
CMDMVW:	MOVEI	T2,DIR.W	;OR FOR WEST
	JRST	SAVMOV		;JOIN COMMON CODE

CMDBCK:	MOVEI	T2,DIR.BK	;FLAG BACKWARDS MOTION WANTED


SAVMOV:	CALL	GETPTC		;READ IN THE LIST OF DIRECTIONS TO MOVE
	CALL	TELROB		;MENTION ANY ROBBERIES
	MOVE	T3,[POINT PTHWID,MOVLST]	;GET POINTER TO DIRECTIONS
	MOVEM	T3,MOVPTR	;SAVE POINTER


MOVLOP:	ILDB	T1,MOVPTR	;GET NEXT DIRECTION
	CAIN	T1,PTHMSK	;END OF THE LIST?
	JRST	LOOK		;YES, DESCRIBE VIEW
	CALL	LOCK		;LOCK UP THE FILE
	LDB	T1,MOVPTR	;GET BACK DIRECTION
	CALL	DOMOVE		;MAKE A MOVE IN THIS DIRECTION
	 RET			;CAN'T, RETURN WITH MESSAGE TYPED
	CALL	UNLOCK		;UNLOCK FILE AGAIN
	CALL	NOTICE		;SEE IF WE SHOULD STOP
	 JRST	MOVLOP		;NO, CONTINUE MOVING
	MOVE	T4,MOVPTR	;GET COPY OF POINTER
	ILDB	T4,T4		;GET NEXT DIRECTION
INTRST:	CAIE	T4,PTHMSK	;INTERRUPTED IN MIDDLE?
	STROUT	[ASCIZ/
While you are following this path, you stumble into a nonempty room.
/]				;YES, SAY SOMETHING
	JRST	LOOK		;GO LOOK AROUND NOW
	SUBTTL	SUBROUTINE TO MAKE A NORMAL TYPE MOVE




;THIS ROUTINE IS CALLED TO MOVE FROM THE CURRENT ROOM TO AN ADJACENT
;ROOM IN A CERTAIN DIRECTION.  MUST BE CALLED WITH DATA FILE LOCKED.
;CALL:	T1/	DIRECTION TO MOVE
;	R/	POINTER TO CURRENT ROOM
;RETURNS:
;  +1:	MOVEMENT NOT POSSIBLE, FILE UNLOCKED AND MESSAGE TYPED
;  +2:	MOVEMENT COMPLETE, FILE STILL LOCKED



DOMOVE:	CAIE	T1,DIR.BK	;WANTS BACKWARDS MOTION?
	JRST	MOVNOB		;NO, PROCEED
	SKIPN	T1,U.BACK(U)	;YES, GET BACKWARDS DIRECTION
	JRST	NOBACK		;THERE WAS NONE, GO COMPLAIN
	ANDI	T1,-1		;KEEP ONLY THE DIRECTION
MOVNOB:	SKIPL	T1		;VERIFY THE DIRECTION
	CAIL	T1,DIRMAX	;AS VALID
	 FATAL	(Trying to move in an illegal direction)
	MOVEM	T1,MOVDIR	;SAVE DIRECTION TO MOVE
	ADDI	T1,R.DIRS(R)	;MAKE ADDRESS OF PROPER LINK WORD
	MOVEM	T1,MOVLNK	;SAVE FOR LATER USE
	SKIPN	T4,R.MONS(R)	;IS THERE A MONSTER IN THIS ROOM?
	JRST	MOVNOM		;NOPE, PROCEED
	HRRO	T1,MOVDIR	;GET INTENDED DIRECTION
	CAMN	T1,U.BACK(U)	;JUST TRYING TO BACK OUT OF ROOM?
	JRST	MOVNOM		;YES, ALLOW THAT
	MOVX	T1,UF.OKM	;GET FLAG
	TDNE	T1,U.FLAG(U)	;CAN WE FLEE THE MONSTER?
	JRST	MOVNOM		;YES, LET US FLEE HIM
	MOVEI	T1,IT.INV	;GET CODE FOR INVISIBILITY RING
	CALL	GETITU		;SEE IF WE HAVE ANY
	JUMPE	T2,NOMMON	;NO, THEN CAN'T GET BY
	MOVX	T1,UF.NIV	;GET INVISIBILY NO GOOD FLAG
	TDNE	T1,U.FLAG(U)	;SEE IF WE TRIED ALREADY
	JRST	NOMMO2		;YES, FAIL AGAIN
	MOVEI	T1,2		;GET A CHANCE
	CALL	RANDOM		;SEE IF WE MAKE IT BY HIM
	JUMPE	T1,NOMMO2	;NOPE
MOVNOM:	HRRO	T1,MOVDIR	;GET DIRECTION OF MOVEMENT
	CAMN	T1,U.BACK(U)	;IS HE TRYING TO BACK UP?
	JRST	EXTDOR		;YES, JUST LET HIM DO IT
	LDB	T1,[POINTR @MOVLNK,DR%TYP]	;GET TYPE OF DOOR TO GO THROUGH
	CALL	@TRYDIR(T1)	;SEE IF WE CAN GO THIS WAY
	 JRST	NOMOVE		;NO, GO SAY WHY
	HRRE	T1,@MOVLNK	;GET ROOM LINK WORD POINTS TO
	AOJN	T1,EXTDOR	;GO ON IF GOES TO AN EXISTANT ROOM
	MOVE	T1,MOVDIR	;NEED A NEW ROOM, GET DIRECTION
	CALL	BUILD		;LINK IN A NEW ROOM TO THIS ONE
	 JRST	NOBLD		;FAILED, HAVE TO CAVE IN THIS DOOR

EXTDOR:	HRRZ	T1,@MOVLNK	;GET WHICH ROOM LINK POINTS TO
	CALL	ENTERM		;MOVE TO THAT ROOM
	MOVE	T1,MOVDIR	;GET DIRECTION WE MOVED IN
	XORI	T1,1		;REVERSE IT FOR BACKWARDS DIRECTION
	HRROM	T1,U.BACK(U)	;AND SAVE IT
	JRST	CPOPJ1		;AND GIVE GOOD RETURN
NOBLD:	MOVEI	T1,[ASCIZ/That passageway has just caved in!!/]	;GET TEXT
	HRLOI	T2,DR.BLK	;GET DOOR TYPE FOR A CAVE-IN
	EXCH	T2,@MOVLNK	;GET OLD TYPE AND SAVE THIS TYPE
	LDB	T2,[POINTR T2,DR%TYP]	;GET TYPE
	CAIE	T2,DR.ALW	;NORMAL TYPE DOOR WE COLLAPSED?
	CAIN	T2,DR.SRC	;OR A SECRET DOOR?
	SKIPA	T2,R.LEVL(R)	;YES, GET LEVEL OF THIS ROOM
	JRST	NOMOVE		;NOPE, JUST GO COMPLAIN
	CAMN	T2,H.LEVL	;YES, REMOVING DOOR FROM LOWEST LEVEL?
	SOS	H.LGRW		;YES, REDUCE COUNT OF GROWABLE DOORS
	JRST	NOMOVE		;AND JOIN COMMON CODE


NOBACK:	MOVEI	T1,[ASCIZ/There is no way to back up from here./]

NOMOVE:	PUSH	P,T1		;SAVE THE ERROR STRING
	CALL	UNLOCK		;UNLOCK THE DATA FILE FIRST
	DOCRLF			;DO A CRLF
	POP	P,T1		;RESTORE STRING
	STROUT	(T1)		;GIVE THE ERROR MESSAGE
	DOCRLF			;END IN A CRLF
NOMOVF:	LDB	T1,[POINT PTHWID,MOVLST,2*PTHWID-1]	;GET 2ND BYTE
	CAIE	T1,PTHMSK	;JUST A 1 MOVE COMMAND?
	CALL	LOOKVR		;NO, DESCRIBE ROOM WE'RE IN
	RET			;DONE


NOMMO2:	MOVX	T1,UF.NIV	;GET INVISIBILITY NO GOOD FLAG
	IORM	T1,U.FLAG(U)	;REMEMBER NOT GOOD HERE
	CALL	UNLOCK		;UNLOCK THE FILE
	DOCRLF			;START WITH CRLF
	STROUT	[ASCIZ/Your invisibility ring was not effective this time.  /]
	SKIPA			;PROCEED

NOMMON:	CALL	UNLOCK		;UNLOCK THE FILE
	STROUT	[ASCIZ/
The /]				;START OUTPUT
	HRRZ	T1,MONTXT(T4)	;GET STRING FOR THIS MONSTER
	CALL	MONOUT		;OUTPUT IT
	STROUT	[ASCIZ/ prevents you from crossing the room.  /]
	DOCRLF			;FINISH WITH CRLF
	JRST	NOMOVF		;AND FINISH
;COMND TABLE FOR FURTHER DIRECTIONS:



DIRCMT:	XWD	CMTLEN,CMTLEN	;HEADER WORD
	AC	BACK-UP,DIR.BK	;BACK TO PREVIOUS ROOM
	AC	EAST,DIR.E	;EAST
	AC	NORTH,DIR.N	;NORTH
	AC	SOUTH,DIR.S	;SOUTH
	AC	WEST,DIR.W	;WEST

	CMTLEN==.-DIRCMT-1	;SIZE OF TABLE



;TABLE OF ROUTINES TO SEE IF A PARTICULAR DIRECTION CAN BE
;TRAVERSED.  SKIP RETURN IF THE DIRECTION IS ALLOWED.  NON-SKIP
;IF NOT POSSIBLE, WITH T1 CONTAINING ADDRESS OF EXPLAINATORY
;TEXT, OR ZERO IF NONE.


TRYDIR:	EXP	NEWDOR		;(0) SHOULDN'T GET HERE
	EXP	NODOR		;(1) NEVER POSSIBLE
	EXP	CPOPJ1		;(2) ALWAYS POSSIBLE
	EXP	SECDOR		;(3) SECRET DOOR
	EXP	LVLDOR		;(4) REQUIRES LEVEL DOOR
	EXP	WRDDOR		;(5) REQUIRES MAGIC WORD
	EXP	MAGDOR		;(6) REQUIRES MAGIC ITEM
	EXP	DEADOR		;(7) COLLAPSED DOOR



SECDOR:	MOVEI	T1,R.SRCF(R)	;GET WHICH WORD TO SET UP
	CALL	BITSET		;MAKE ADDRESS AND BIT FOR TESTING
	TDNE	T2,(T1)		;DID WE SEARCH THE ROOM?
	JRST	CPOPJ1		;YES, ALLOW THIS THEN
NODOR:	MOVEI	T1,[ASCIZ/You can't go that way./]
	RET			;RETURN ERROR

NEWDOR:	MOVEI	T1,[ASCIZ/This is a new door not yet completed./]
	RET			;RETURN BAD

DEADOR:	MOVEI	T1,[ASCIZ/There is a cave-in in that direction!!/]
	RET			;RETURN BAD

LVLDOR:	JRST	CPOPJ1		;YES, GOOD RETURN
	MOVEI	T1,[ASCIZ/You are not good enough to go through the door./]
	RET			;RETURN MAD

WRDDOR:	LDB	T1,[POINTR @MOVLNK,DR%DAT]	;GET DATA FOR THIS DOOR
	JUMPN	T1,CPOPJ1	;IF NONZERO, CAN GO THROUGH THE DOOR
	HRRE	T1,@MOVLNK	;GET LINKED ROOM
	JUMPL	T1,WRDNO	;IF NONE, FAIL
	IMULI	T1,ROMSIZ	;COMPUTE ADDRESS OF THAT ROOM
	MOVE	T2,MOVDIR	;GET DIRECTION
	XORI	T2,1		;REVERSE IT
	ADD	T1,T2		;ADD IN
	LDB	T1,[POINTR R.DIRS(T1),DR%DAT]	;GET DATA THERE
	JUMPN	T1,CPOPJ1	;SUCCESSFUL IF OPEN
WRDNO:	MOVEI	T1,[ASCIZ/The magic word door is not opened./]
	RET			;RETURN BAD

MAGDOR:	LDB	T1,[POINTR @MOVLNK,DR%DAT]	;GET DATA
	JUMPE	T1,CPOPJ1	;GOOD RETURN IF IT'S OPEN
	MOVEI	T1,[ASCIZ/You haven't used the proper magic item to open the doo
r./]
	RET			;RETURN BAD
;SUBROUTINE TO SEE IF A MAGIC TORCH HAS LIT UP THE CURRENT ROOM.



DOTORC:	MOVEI	T1,IT.GLS	;GET CODE FOR MAGIC GLASSES
	CALL	GETITU		;SEE IF WE HAVE ANY
	JUMPE	T2,CPOPJ	;IF NONE, RETURN
	MOVEI	T1,R.SRCF(R)	;GET ADDRESS OF SEARCH FLAGS
	CALL	BITSET		;POINT TO PROPER BIT
	IORM	T2,(T1)		;SAY WE KNOW ABOUT SECRET PASSAGES
	MOVEI	T1,2		;GET READY
	CALL	RANDOM		;TO SEE IF WE FIND TREASURE TOO
	JUMPE	T1,CPOPJ	;RETURN IF NO
	MOVEI	T1,R.HIDF(R)	;GET ADDRESS OF FLAGS
	CALL	BITSET		;POINT TO THE BIT FOR US
	IORM	T2,(T1)		;SAY WE CAN SEE TREASURE HERE
	RET			;DONE
	SUBTTL	SUBROUTINE TO READ IN A LIST OF DIRECTIONS






;THIS SUBROUTINE IS USED TO READ IN THE REST OF THE COMMAND LINE,
;AND TO STORE THE DIRECTIONS IN THE MOVLST TABLE FOR LATER USE.
;NUMBER OF DIRECTIONS READ IS STORED IN PTHCNT.  CALL
;AT GETPTC IF T2 HAS FIRST DIRECTION ALREADY.
;RETURNS:
;  +1:	REST OF LINE EATEN, WITH DIRECTIONS STORED IN MOVLST.
;USES LOTS OF AC'S.




GETPTH:	CMMD	[FLDDB. (.CMKEY,,DIRCMT)]	;PARSE DIRECTION
	HRRZ	T2,(T2)		;GET CODE
GETPTC:	MOVE	T3,[POINT PTHWID,MOVLST]	;GET POINTER
	MOVEM	T3,MOVPTR	;SET UP POINTER
	SETZM	PTHCNT		;CLEAR COUNTER

GETPTL:	AOS	T3,PTHCNT	;ADVANCE ENTRY
	CAILE	T3,MOVMAX-1	;OVERFLOWED THE TABLE?
	 ERROR	(,,Too many directions specified.)	;YES
	IDPB	T2,MOVPTR	;STORE THE DIRECTION
	NOISE	(THEN)		;GIVE SOME NOISE TEXT
	CMMD	[FLDDB. (.CMCFM,,,,,<[FLDDB. (.CMKEY,,DIRCMT)]>)]
	TSC	T3,T3		;SEE IF GAVE ANOTHER KEYWORD
	JUMPE	T3,GETPTE	;NO, FINISH UP
	HRRZ	T2,(T2)		;GET THE DIRECTION CODE
	JRST	GETPTL		;AND LOOP

GETPTE:	MOVEI	T2,-1		;GET READY
	IDPB	T2,MOVPTR	;END THE LIST OF MOVES
	RET			;DONE
	SUBTTL	SUBROUTINE TO MOVE TO A ROOM




;THIS SUBROUTINE IS USED TO MOVE US TO A PARTICULAR ROOM.  ALL
;THE NECESSARY BOOKKEEPING IS DONE HERE FOR THIS.  IE, DOORS ARE
;BUILT, MONSTERS AND TREASURE ARE CREATED, VISIT AND MOVE COUNTS
;ARE UPDATED, ETC.  CALL:
;	T1/	NEW ROOM NUMBER
;RETURNS:
;  +1:	ALWAYS, WITH EVERYTHING UPDATED
;	R/	POINTS TO THE NEW ROOM
;THE FLAG FR.VR2 IS SET IF WE HAVE NEVER BEEN HERE BEFORE.
;CALL AT ENTERM IF MONSTERS PREVENT MOVEMENT LATER.



ENTERM:	TDZA	T2,T2		;GET NO FLAG
ENTER:	MOVX	T2,UF.OKM	;OR GET THE OK TO MOVE FLAG
	SKIPL	T1		;MAKE SURE ROOM IS POSITIVE
	CAMLE	T1,H.ROOM	;AND NOT TOO LARGE
	 FATAL	(Entering illegal room number)
	MOVE	T3,T1		;GET COPY OF ROOM NUMBER
	IMULI	T3,ROMSIZ	;CREATE POINTER TO IT
	ADDI	T3,ROMADR	;FINISH IT
	MOVE	T4,R.ROOM(T3)	;GET ROOM NUMBER IT SAYS IT IS
	TLC	T4,-1		;COMPLEMENT FOR CHECK
	CAMN	T1,T4		;CORRECT?
	TLNE	T4,-1		;WELL?
	 JRST	BADROM		;NOPE, GO COMPLAIN
	MOVE	T4,R.LEVL(R)	;SAVE LEVEL OLD ROOM WAS IN
	MOVE	R,T3		;THEN POINT TO THE NEW ROOM
	SETZM	U.BACK(U)	;BACKING UP IS ILLEGAL UNTIL KNOW OTHERWISE
	IORM	T2,U.FLAG(U)	;SET OK TO MOVE ANY DIRECTION FLAG
	MOVEM	T1,U.ROOM(U)	;SET OUR NEW ROOM NUMBER
	SUB	T4,R.LEVL(R)	;GET LEVEL CHANGE
	MOVM	T4,T4		;KEEP ONLY ABSOLUTE VALUE
	ADDI	T4,1		;ONE MORE IN CASE NO LEVEL CHANGE
	ADDM	T4,U.TURN(U)	;BUMP NUMBER OF MOVES USED
	MOVE	T1,PLYUSR	;GET MY USER NUMBER
	SKIPN	R.VIST(R)	;ANYBODY BEEN HERE BEFORE?
	MOVEM	T1,R.FVIS(R)	;NO, REMEMBER WE WERE FIRST
	MOVEM	T1,R.LVIS(R)	;ALSO REMEMBER WHO WAS LAST HERE
	SKIPN	R.VIST(R)	;WAS THIS ROOM VISITED BEFORE?
	AOS	U.BLDR(U)	;NO, ADD TO ROOMS WE'VE DISCOVERED
	AOS	R.VIST(R)	;INCREMENT NUMBER OF VISITS TO ROOM
	MOVEI	T1,R.VISF(R)	;GET ADDRESS OF VISIT TABLE
	CALL	BITSET		;THEN READY THE BIT
	TDNN	T2,(T1)		;HAVE WE BEEN HERE BEFORE?
	AOSA	U.NEWR(U)	;NO, INCREMENT ROOMS VISITED
	TXZA	F,FR.VR2	;YES, CLEAR THE TEMPORARY VERBOSE FLAG
	TXO	F,FR.VR2	;NO, SET TEMPORARY VERBOSITY
	IORM	T2,(T1)		;THEN REMEMBER WE'VE BEEN HERE
	HRRZ	T1,R.LEVL(R)	;GET LEVEL OF THIS ROOM
	CAMLE	T1,U.LEVL(U)	;LOWER DOWN THAN OUR OWN LEVEL?
	MOVEM	T1,U.LEVL(U)	;YES, REMEMBER OUR NEW LEVEL
	MOVX	T1,UF.OKM!UF.NIV	;GET FLAGS
	ANDCAM	T1,U.FLAG(U)	;CLEAR FROM FLAG WORD
	CALL	DOFIX		;TRY TO FIX US UP A LITTLE
	CALL	DOTORC		;SEE IF TORCH LIGHTS UP THE ROOM
	CALL	MAKDOR		;DECIDE WHAT KIND OF DOORS EXIST HERE
	CALL	MAKTRE		;PUT TREASURE IN THE ROOM IF NECESSARY
	MOVE	T1,[^D30,,^D60]	;GET NORMAL CHANCE FOR MONSTERS
	CALL	MAKMON		;PUT A MONSTER HERE IF NECESSARY
	CALL	MAKITM		;PUT A MAGICAL ITEM HERE IF NECESSARY
	GTAD			;READ TIME
	MOVEM	T1,U.LDAT(U)	;REMEMBER WHEN WE LAST MOVED
	RET			;DONE



;HERE IF WE ARE TRYING TO ENTER A BAD ROOM:


BADROM:	MOVEM	T1,TEMP		;SAVE ROOM NUMBER
	CALL	UNLOCK		;UNLOCK THE FILE
	STROUT	[ASCIZ/
You cannot enter room /]	;TYPE
	DECOUT	TEMP		;THEN GIVE ROOM NUMBER
	STROUT	[ASCIZ/ because it has been trashed.

/]				;FINISH IT
	JRST	DOERRF		;THEN FINISH THE ERROR
	SUBTTL	ROUTINE TO SEE IF A ROOM IS INTERESTING




;THIS IS CALLED WHILE MOVING ALONG A LONG PATH TO SEE IF SOMETHING
;INTERESTING IS IN THIS ROOM.  INTERESTING MEANS THE ROOM CONTAINS
;TREASURE, ITEMS, OR MONSTERS.  CALL:
;	R/	POINTER TO ROOM
;RETURNS:
;  +1:	NOTHING INTERESTING FOUND
;  +2:	INTERESTING THINGS FOUND
;CALL AT HIDCHK TO JUST SEE IF WE HAVE SEARCHED ROOM.
;PRESERVES T4.




NOTICE:	SKIPN	R.VTRE(R)	;ANY VISIBLE TREASURE HERE?
	SKIPE	R.VITM(R)	;OR VISIBLE ITEMS?
	JRST	CPOPJ1		;YES
	SKIPE	R.MONS(R)	;ANY MONSTERS HERE?
	JRST	CPOPJ1		;YES
	SKIPN	R.HTRE(R)	;ANY HIDDEN TREASURE?
	SKIPE	R.HITM(R)	;OR HIDDEN ITEMS?
	JRST	HIDCHK		;YES, SEE IF SEARCHED ROOM
	RET			;NO, NOTHING INTERESTING HERE


HIDCHK:	MOVEI	T1,R.HIDF(R)	;GET READY
	CALL	BITSET		;MAKE OFFSET AND MASK
	TDNE	T2,(T1)		;HAS ROOM BEEN SEARCHED BY US?
	AOS	(P)		;YES, SKIP RETURN
	RET			;DONE
	SUBTTL	SUBROUTINE TO COMPUTE SHIFTS



;SUBROUTINE TO COMPUTE HOW MUCH TO SHIFT BY WHEN MOVING FROM A ROOM
;TO A NEARBY ROOM.  WHEN WE GO A PARTICULAR DIRECTION, WE WILL SHIFT
;COORDINATES BY 10 OR SO, WITH A LITTLE BIT OF RANDOMNESS.  IN ADDITION,
;WE WILL SHIFT SIDEWAYS A LITTLE BIT.
;CALL:	T1/	CURRENT COORDINATES
;	T2/	DIRECTION CODE OF SHIFT
;
;RETURNS:
;	T1/	NEW COORDINATES



SHIFT:	MOVEM	T1,TEMP		;SAVE AWAY THE COORDINATES
	MOVE	T4,T2		;AND PUT DIRECTION IN SAFE AC
	MOVEI	T1,SFPMAX-SFPMIN-1	;GET A NICE RANGE
	CALL	RANDOM		;AND GENERATE A RANDOM NUMBER
	MOVEI	T3,SFPMIN(T1)	;THEN SAVE PRIMARY SHIFT DISTANCE
	MOVEI	T1,SFSMAX*2+1	;GET ANOTHER NICE RANGE
	CALL	RANDOM		;THEN ANOTHER RANDOM NUMBER
	SUBI	T1,SFSMAX	;PRODUCE SECONDARY SHIFT DISTANCE
	HLRZ	T2,TEMP		;GET CURRENT X COORDINATE
	XCT	XSHIFT(T4)	;MODIFY IT DEPENDING ON DIRECTION
	HRLM	T2,TEMP		;SAVE RESULT
	HRRZ	T2,TEMP		;GET CURRENT Y COORDINATE
	XCT	YSHIFT(T4)	;MODIFY IT DEPENDING ON DIRECTION
	HRRM	T2,TEMP		;SAVE RESULT
	MOVE	T1,TEMP		;RETRIEVE NEW COORDINATES
	RET			;DONE


XSHIFT:	ADD	T2,T1		;NORTH
	ADD	T2,T1		;SOUTH
	ADD	T2,T3		;EAST
	SUB	T2,T3		;WEST

YSHIFT:	ADD	T2,T3		;NORTH
	SUB	T2,T3		;SOUTH
	ADD	T2,T1		;EAST
	ADD	T2,T1		;WEST
	SUBTTL	SUBROUTINE TO PRODUCE A DESCRIPTION OF THE CURRENT ROOM




;CALLED AFTER EVERY MOVE HAS BEEN MADE, TO PRODUCE A DESCRIPTION OF
;THE CURRENT ROOM.  THE DESCRIPTION DEPENDS ON THE LOCATION OF THE
;ROOM, THE ROOM NUMBER, AND WHICH KINDS OF PASSAGEWAYS LEAD AWAY.



LOOKVR:	TXO	F,FR.VR2	;SET TEMPORARY VERBOSITY FLAG
LOOK:	TXNN	F,FR.DEB	;DOING DEBUGGING STUFF?
	JRST	LOOKNM		;NO, SKIP THIS STUFF
	STROUT	[ASCIZ/
Room /]				;GET READY
	HRRZ	T1,R.ROOM(R)	;GET THE ROOM NUMBER
	CALL	TTYDEC		;OUTPUT IT
	STROUT	[ASCIZ/ at /]	;MORE
	HLRZ	T1,R.LOC(R)	;GET X COORDINATE
	CALL	TTYDEC		;OUTPUT IT
	CHROUT	","		;THEN A COMMA
	HRRZ	T1,R.LOC(R)	;GET Y COORDINATE
	CALL	TTYDEC		;OUTPUT IT
	STROUT	[ASCIZ/ in level /]	;MORE
	DECOUT	R.LEVL(R)	;OUTPUT LEVEL
	STROUT	[ASCIZ/ at file address /]	;MORE
	HRRZ	T1,R.ROOM(R)	;GET ROOM NUMBER
	IMULI	T1,ROMSIZ	;MULTIPLY BY SIZE OF EACH ROOM'S DATA
	ADDI	T1,ROMADR-MAPADR	;ADD IN OFFSET INTO THE FILE
	CALL	TTYOCT		;OUTPUT IT
	STROUT	[ASCIZ/
Discovered by: /]		;GET READY
	MOVE	T1,R.FVIS(R)	;GET WHO DISCOVERED THIS ROOM
	CALL	USROUT		;OUTPUT IT
	STROUT	[ASCIZ/,  Visits: /]	;MORE
	DECOUT	R.VIST(R)	;TYPE IT
	STROUT	[ASCIZ/
Visible treasure: /]			;MORE
	DECOUT	R.VTRE(R)	;TYPE IT
	STROUT	[ASCIZ/,  Hidden treasure: /]	;MORE TEXT
	DECOUT	R.HTRE(R)	;TYPE IT
	STROUT	[ASCIZ/, Monster: /]	;MORE
	SKIPN	T4,R.MONS(R)	;ANY?
	STROUT	[ASCIZ/None/]	;NO
	JUMPE	T4,DEBLNM	;SKIP IF THAT'S IT
	HRRZ	T1,MONTXT(T4)	;GET NAME
	CALL	MONOUT		;TYPE IT
	STROUT	[ASCIZ/ (strength = /]	;MORE
	DECOUT	R.MONH(R)	;OUTPUT IT
	CHROUT	")"		;FINISH
DEBLNM:	DOCRLF			;DO A CRLF
	MOVSI	I,-DIRMAX	;GET READY FOR LOOPING
	ADDI	I,R.DIRS(R)	;OVER ALL DIRECTIONS

LKDBLP:	MOVE	T1,(I)		;GET DOOR TYPE
	CAMN	T1,[DR.NEV,,-1]	;IS THIS A STANDARD NONEXISTANT DOOR?
	JRST	LKDBNX		;YES, SKIP ON
	CHROUT	" "		;SPACE OVER
	MOVEI	T1,(I)		;GET OFFSET
	SUBI	T1,R.DIRS(R)	;UNDO OFFSET
	STROUT	@DORTXT(T1)	;OUTPUT DIRECTION
	STROUT	[ASCIZ/:	  /]	;THEN TAB OVER
	LDB	T4,[POINTR 0(I),DR%TYP]	;GET TYPE
	STROUT	@LKDTBL(T4)	;GIVE THE DOOR TYPE
	STROUT	[ASCIZ/ door/]	;TYPE MORE
	MOVE	T1,(I)		;GET POINTER
	HRREI	T1,(T1)		;GET ROOM NUMBER
	SKIPL	LKDTBL(T4)	;DOES THIS GO TO ANY ROOM?
	AOJE	T1,LKDBDN	;OR IS ROOM ALLOCATED?
LKDTYR:	HRRZ	T4,(I)		;GET ROOM
	CAIN	T4,-1		;UNALLOCATED ROOM?
	STROUT	[ASCIZ/ to an unallocated room/]	;YES, TYPE STUFF
	CAIN	T4,-1		;WELL?
	JRST	LKDBDN		;YES, SKIP ON
	STROUT	[ASCIZ/ to room /]	;TYPE ROOM NUMBER STRING
	HRRZ	T1,(I)		;GET ROOM
	DECOUT	T1		;OUTPUT IT
LKDBDN:	DOCRLF			;DO A CRLF
LKDBNX:	AOBJN	I,LKDBLP	;LOOP OVER ALL DIRECTIONS
;HERE TO GIVE THE NORMAL DESCRIPTION THAT ALL PLAYERS SEE:



LOOKNM:	DOCRLF			;TYPE A CRLF
	TXNE	F,FR.VRB!FR.VR2	;VERBOSE OUTPUT?
	TDZA	T1,T1		;YES, SUPPRESS ANY TEXT
	MOVEI	T1,[ASCIZ/This is the entrance to the dungeon/]	;GET TEXT
	HRRZ	T4,R.ROOM(R)	;GET ROOM NUMBER
	SKIPE	T4		;IS THIS ROOM ZERO?
	MOVEI	T1,[ASCIZ/This is room /]	;NO, GET NORMAL TEXT
	JUMPE	T1,LOOKNT	;SKIP IF NO TEXT
	CALL	TTYSTR		;YES, OUTPUT IT
	SKIPE	T1,T4		;GET ROOM NUMBER READY
	CALL	TTYDEC		;AND OUTPUT IT IF NONZERO
	STROUT	[ASCIZ/.  /]	;TYPE MORE TEXT
LOOKNT:	TXNN	F,FR.VRB!FR.VR2	;VERBOSE OUTPUT DESIRED?
	JRST	LOOKBF		;NO, SKIP SOME
	CALL	LKROOM		;MAKE UP SOME STUFF ABOUT THIS ROOM
	CALL	LKDEAD		;LOOK FOR DEAD THINGS
	CALL	LKPASS		;LOOK FOR OBVIOUS PASSAGES
	CALL	LKSECR		;LOOK FOR SECRET PASSAGES
	CALL	LKBLCK		;LOOK FOR BLOCKED PASSAGES
LOOKBF:	CALL	LKLEVL		;LOOK FOR LEVEL-CHANGE DOORS
	CALL	LKWORD		;LOOK FOR A WORD ON THE WALL
	CALL	LKUSER		;LOOK FOR OTHER USERS IN THE ROOM
	CALL	LKTRES		;LOOK FOR ANY TREASURE
	CALL	LKITEM		;LOOK FOR ANY MAGIC ITEMS
	CALL	LKMONS		;LOOK FOR ANY MONSTERS HERE
	TXZ	F,FR.VR2	;CLEAR TEMPORARY VERBOSITY FLAG
	DOCRLF			;TYPE A CRLF
	RET			;DONE
;SUBROUTINE TO LOOK FOR OBVIOUS PASSAGES FROM THIS ROOM, AND OUTPUT
;THE DIRECTIONS THEY GO.  ALSO HERE TO LOOK FOR SECRET PASSAGES.



LKSECR:	TDNN	ZR,R.ROOM(R)	;AT THE ENTRANCE?
	RET			;YES, NONE OF THIS OUTPUT IS DONE
	MOVEI	T1,R.SRCF(R)	;GET ADDRESS OF SEARCH FLAGS
	CALL	BITSET		;THEN SETUP FOR TESTING
	TDNN	T2,(T1)		;WAS THIS ROOM SEARCHED BEFORE?
	RET			;NO, RETURN

LKSEC2:	MOVEI	T1,DR.SRC	;YES, GET SECRET DOOR TYPE
	CALL	FNDDOR		;LOOK FOR THAT TYPE OF DOOR
	MOVE	T4,T1		;REMEMBER HOW MANY
	MOVEI	T1,[ASCIZ/No secret passages leave here.  /]	;TEXT
	JUMPE	T4,TTYSTR	;TYPE IT IF NO PASSAGES
	MOVEI	T1,[ASCIZ/A secret passage leads /]	;TEXT
	CAIN	T4,1		;ONLY ONE SECRET PASSAGE?
	CALL	TTYSTR		;YES, OUTPUT IT
	MOVEI	T1,[ASCIZ/Secret passages lead /]	;TEXT
	JRST	OBSHOW		;JOIN OTHER CODE



LKBLCK:	MOVEI	T1,DR.BLK	;GET TYPE OF DOOR
	CALL	FNDDOR		;LOOK FOR THAT TYPE
	SKIPN	T4,T1		;SAVE NUMBER OF CRASHED IN DOORS
	RET			;IF NONE, TYPE NOTHING
	CAIN	T4,1		;ONLY ONE CAVED IN DOORWAY?
	STROUT	[ASCIZ/A caved-in doorway prevents moving /]	;YES
	MOVEI	T1,[ASCIZ/Caved-in doorways prevent moving /]
	JRST	OBSHOW		;JOIN OTHER CODE



LKPASS:	TDNN	ZR,R.ROOM(R)	;AT ENTRANCE?
	RET			;YES, DON'T MENTION PASSAGES
	MOVEI	T1,DR.ALW	;GET TYPE OF DOOR
	CALL	FNDDOR		;LOOK FOR THAT TYPE OF DOOR
	MOVE	T4,T1		;REMEMBER NUMBER OF DOORS
	MOVEI	T1,[ASCIZ/No passages leave here.  /]	;TEXT
	JUMPE	T4,TTYSTR	;TYPE IT IF NO PASSAGES
	CAIN	T4,1		;ONLY ONE OBVIOUS PASSAGE?
	STROUT	[ASCIZ/A passage leads /]	;YES, TYPE TEXT
	MOVEI	T1,[ASCIZ/Passages lead /]	;TEXT

OBSHOW:	CAIE	T4,1		;MORE THAN ONE PASSAGE?
	CALL	TTYSTR		;YES, SAY THAT
	MOVEI	T1,[ASCIZ/in all directions.  /]	;TEXT
	CAIN	T4,DIRMAX	;ALL DIRECTIONS USED?
	JRST	TTYSTR		;YES, FINISH UP NOW
	MOVSI	I,-DIRMAX	;MAKE AOBJN POINTER TOO
	SETZM	LISOLD		;GET READY FOR LIST OUTPUT

OBLOOP:	SKIPN	DORTAB(I)	;IS THIS ONE OF THE DOORS?
	JRST	OBNEXT		;NO, LOOP ONWARD
	HRLZ	T1,DORTXT(I)	;GET ADDRESS OF TEXT
	IORI	T1,TTYSTR	;AND ROUTINE TO CALL
	CALL	DOLIST		;OUTPUT DIRECTION IN A LIST
OBNEXT:	AOBJN	I,OBLOOP		;LOOP OVER ALL DIRECTIONS
	CALL	DOLISE		;TERMINATE THE LIST
	MOVEI	T1,[ASCIZ/.  /]	;GET TEXT
	JRST	TTYSTR		;OUTPUT IT
;SUBROUTINE TO TYPE OUT ALL DOORS WHICH CHANGE LEVELS.



LKLEVL:	MOVSI	I,-DIRMAX	;GET SET FOR A LOOP

LVLOOP:	HRRZ	T4,I		;GET INDEX BY ITSELF
	ADDI	T4,R.DIRS(R)	;MAKE ADDRESS OF THE DIRECTION POINTER
	LDB	T1,[POINTR 0(T4),DR%TYP]	;GET DOOR TYPE
	CAIE	T1,DR.LVL	;IS THIS A LEVEL CHANGE DOOR?
	JRST	LVLNXT		;NO, GO TO NEXT DIRECTION
	STROUT	[ASCIZ/There is a huge stone door on the /]	;TEXT
	STROUT	@DORTXT(I)	;TYPE DIRECTION
	STROUT	[ASCIZ/ wall, with the phrase "/]	;TEXT
	HRRE	T3,(T4)		;GET ROOM THAT WE LINK TO
	JUMPL	T3,[MOVE T3,R.LEVL(R)	;NOPLACE, THEN GET CURRENT LEVEL
		    AOJA T3,LVLOUT]	;INCREMENT IT AND TYPE IT
	IMULI	T3,ROMSIZ	;GET OFFSET INTO ROOM DATA
	MOVE	T3,ROMADR+R.LEVL(T3)	;THEN GET LEVEL WE ARE GOING TO
LVLOUT:	MOVEI	T1,[ASCIZ/DOWN TO LEVEL /]	;GET A TEXT
	CAMGE	T3,R.LEVL(R)	;ACTUALLY MOVING UP?
	MOVEI	T1,[ASCIZ/UP TO LEVEL /]	;YES, OTHER TEXT
	SKIPN	T3		;GOING TO THE ENTRANCE?
	MOVEI	T1,[ASCIZ/ENTRANCE/]	;YES, GET THAT
	CALL	TTYSTR		;TYPE PROPER TEXT
	SKIPE	T1,T3		;NEED NUMBER?
	CALL	TTYDEC		;YES, TYPE LEVEL NUMBER
	STROUT	[ASCIZ/" carved in it.  /]

LVLNXT:	AOBJN	I,LVLOOP	;LOOP OVER ALL LEVELS
	RET			;DONE
;TABLES FOR OUTPUT OF DEBUGGING INFORMATION:


LKDTBL:	0B0+[ASCIZ/unused/]		;(0)
	0B0+[ASCIZ/non-existant/]	;(1)
	1B0+[ASCIZ/direct/]		;(2)
	1B0+[ASCIZ/secret/]		;(3)
	1B0+[ASCIZ/level-change/]	;(4)
	1B0+[ASCIZ/magic word/]		;(5)
	1B0+[ASCIZ/magic item/]		;(6)
	0B0+[ASCIZ/caved-in/]		;(7)



DORTXT:	EXP	[ASCIZ/North/]		;NORTH
	EXP	[ASCIZ/South/]		;SOUTH
	EXP	[ASCIZ/East/]		;EAST
	EXP	[ASCIZ/West/]		;WEST
	EXP	[ASCIZ/Back-up/]	;BACK-UP
	SUBTTL	SUBROUTINE TO MAKE UP A DESCRIPTION OF A ROOM




;CALLED WHEN DESCRIBING A ROOM, TO MAKE UP SOME STUFF ABOUT THE
;ROOM TO MAKE IT MORE INTERESTING.  THIS IS DONE MY TAKING THE
;COORDINATES OF THE ROOM AS A RANDOM NUMBER, AND THEN USING THAT
;TO SELECT AMONG MANY PHRASES.




LKROOM:	TDNN	ZR,R.ROOM(R)	;AT THE ENTRANCE?
	JRST	ATENTR		;YES, SPECIAL OUTPUT FOR HERE
	PUSH	P,RANNUM	;SAVE REAL RANDOM NUMBER
	MOVE	T1,R.LOC(R)	;GET COORDINATES OF ROOM
	IMUL	T1,[^D<125*125*125*125*125>]	;JUMBLE
	ADD	T1,R.ROOM(R)	;ADD IN ROOM NUMBER
	IMUL	T1,[^D<125*125*125*125*125>]	;MORE
	ADD	T1,R.LEVL(R)	;FINALLY ADD LEVEL NUMBER
	IMUL	T1,[^D<125*125*125*125*125>]	;MORE
	ADD	T1,H.DATE	;ADD CREATION TIME OF DUNGEON
	MOVEM	T1,RANNUM	;AND SET AS SEED OF RANDOM NUMBER
	CALL	RANDOM		;CALL IT ONCE FIRST
	MOVE	T1,[TXN1,,TXT1]	;POINT TO THE INTRODUCTION TEXT
	CALL	RANTXT		;OUTPUT THE TEXT
	STROUT	[ASCIZ/ room is /]	;TEXT
	MOVE	T1,[TXN2,,TXT2]	;MORE
	CALL	RANTXT		;MORE TEXT
	STROUT	[ASCIZ/ with /]	;MORE
	MOVE	T1,[TXN3,,TXT3]	;MORE
	CALL	RANTXT		;MORE TEXT
	STROUT	[ASCIZ/.  /]	;FINAL TEXT
	POP	P,RANNUM	;RESTORE REAL RANDOM NUMBER
	RET			;DONE
;HERE IF AT THE ENTRANCE, TO OUTPUT SPECIAL TEXT.



ATENTR:	STROUT	[ASCIZ/&You are standing in the ruins of some ancient
town in the middle of a large desert.  You have discovered by digging
through the ruins that the name of this town was "TESER NIGEB", and
that it was built around the entrance to a huge underground tunnel
system.  Off in the distance are some pretty mountains, however the
only place you can go is down into the dungeon.  /]	;TYPE STUFF
	RET			;DONE




;ROUTINE TO OUTPUT ONE OF VARIOUS TEXTS, GIVEN NUMBER OF TEXTS IN
;LEFT HALF OF T1, AND ADDRESS OF TEXT POINTERS IN RIGHT HALF.


RANTXT:	HRRZ	T4,T1		;SAVE ADDRESS
	HLRZ	T1,T1		;GET NUMBER OF MESSAGES
	CALL	RANDOM		;GENERATE A RANDOM NUMBER
	ADD	T1,T4		;ADD IN ADDRESS OF POINTERS
	HRRZ	T1,(T1)		;THEN GET ADDRESS OF PROPER TEXT
	JRST	TTYSTR		;GO OUTPUT IT
;TABLES USED TO DESCRIBE A ROOM.



	DEFINE	XX(TEXT),<	;;MAKE A USEFUL MACRO
	EXP	[ASCIZ/TEXT/]
>


TXT1:	XX	This
	XX	You can see that this
	XX	<Looking around, you see that this>
	XX	You notice that the
	XX	Here you see that the
	XX	Here the

	TXN1==.-TXT1		;NUMBER OF TEXTS


TXT2:	XX	small
	XX	thin and long
	XX	square
	XX	almost round
	XX	small and drafty
	XX	large
	XX	huge
	XX	dark and damp
	XX	filled with stalactites
	XX	packed with boulders

	TXN2==.-TXT2		;NUMBER OF TEXTS


TXT3:	XX	footprints in the soft sand
	XX	a hard floor
	XX	granite walls
	XX	sandstone walls
	XX	a small pool of water in the corner
	XX	illegible writing on the walls
	XX	a slightly sloping floor
	XX	dirty looking walls

	TXN3==.-TXT3		;NUMBER OF TEXTS
;SUBROUTINE TO TELL ABOUT OTHER USERS IN THIS ROOM.



LKUSER:	HRLZ	I,H.PLRS	;GET NUMBER OF PLAYERS
	MOVN	I,I		;MAKE INTO AOBJN POINTER
	ADDI	I,PLRADR	;POINT TO PLAYERS
	MOVE	T4,U.ROOM(U)	;GET MY ROOM NUMBER
	SETZM	LISOLD		;SET UP TO CALL LIST ROUTINE

LKUSRL:	CAMN	T4,U.ROOM(I)	;IS THIS PLAYER ALSO IN MY ROOM?
	CAIN	U,(I)		;AND NOT MYSELF?
	JRST	LKUSRN		;NO, TRY NEXT GUY
	SKIPN	U.USER(I)	;MAKE SURE THERE IS ONE
	JRST	LKUSRN		;NO, GO TO NEXT GUY
	PUSH	P,U		;SAVE MY LOCATION
	MOVE	U,I		;POINT TO HIS ENTRY
	MOVEI	T1,IT.INV	;GET INVISIBILITY CODE
	CALL	GETITU		;SEE IF HE HAS AN INVISIBILITY RING
	POP	P,U		;RESTORE AC
	JUMPN	T2,LKUSRN	;IF HAS ONE, DON'T SHOW HIM
	MOVSI	T1,U.USER(I)	;GET ADDRESS OF USER NUMBER
	IORI	T1,[MOVE T1,(T1)	;AND INSTRUCTIONS TO TYPE IT
		    JRST USROUT]	;CALLED FROM LIST ROUTINE
	CALL	DOLIST		;OUTPUT THE NAME AS PART OF A LIST

LKUSRN:	ADDI	I,PLRSIZ-1	;MOVE TO NEXT BLOCK
	AOBJN	I,LKUSRL	;LOOP UNTIL DONE
	CALL	DOLISE		;FINISH THE LIST
	SKIPN	T2,LISCNT	;SEE HOW MANY PEOPLE WERE TYPED
	RET			;NONE, RETURN
	MOVEI	T1,[ASCIZ/ is/]	;GET POSSIBLE TEXT
	CAIE	T2,1		;MORE THAN ONE PERSON?
	MOVEI	T1,[ASCIZ/ are/]	;YES, GET OTHER TEXT
	CALL	TTYSTR		;TYPE THE TEXT
	STROUT	[ASCIZ/ here with you.  /]	;FINISH IT
	RET			;DONE





;SUBROUTINE TO OUTPUT HOW MUCH TREASURE IS HERE IN THIS ROOM.
;WE ALWAYS TELL ABOUT VISIBLE TREASURE, BUT ONLY HIDDEN TREASURE
;IF THE ROOM WAS SEARCHED.



LKTRES:	SKIPE	R.MONS(R)	;A MONSTER IN THE ROOM?
	RET			;YES, WE CAN'T SEE STUFF THEN
	MOVEI	T1,R.HIDF(R)	;GET ADDRESS OF HIDE FLAGS
	CALL	BITSET		;MAKE A BIT MASK
	TDNN	T2,(T1)		;CAN WE KNOW ABOUT HIDDEN TREASURE?
	TDZA	T4,T4		;NO, GET NONE
	MOVE	T4,R.HTRE(R)	;YES, GET AMOUNT HIDDEN
	PUSH	P,T4		;SAVE FOR AWHILE
	ADD	T4,R.VTRE(R)	;ADD IN AMOUNT VISIBLE TOO
	JUMPE	T4,LKTREF	;NO OUTPUT IF NOTHING HERE
	STROUT	[ASCIZ/This room has /]	;TYPE SOME
	MOVE	T1,T4		;PUT IN RIGHT AC
	CALL	GOLOUT		;OUTPUT HOW MUCH GOLD
	CAMN	T4,0(P)		;IS ALL OF IT HIDDEN?
	STROUT	[ASCIZ/ hidden/]	;YES, SAY SO
	STROUT	[ASCIZ/ in it/]	;FINISH IT
	CAME	T4,0(P)		;ALL HIDDEN?
	SKIPN	T4,0(P)		;OR NONE HIDDEN?
	JRST	LKTREH		;YES, SKIP SOME
	STROUT	[ASCIZ/ (/]	;START OFF
	DECOUT	T4		;TYPE AMOUNT HIDDEN
	STROUT	[ASCIZ/ of them /]	;MORE
	CAIN	T4,1		;JUST ONE?
	STROUT	[ASCIZ/is/]	;YES
	CAIE	T4,1		;WELL?
	STROUT	[ASCIZ/are/]	;NO
	STROUT	[ASCIZ/ hidden)/]	;FINISH
LKTREH:	STROUT	[ASCIZ/!!!  /]	;FINISH UP
LKTREF:	POP	P,T1		;RESTORE AC
	RET			;AND RETURN
;SUBROUTINE TO TELL ABOUT WORDS SCRAWLED ON THE WALLS.  THESE WORDS
;WILL DO NICE THINGS LIKE OPEN MAGIC DOORS.




LKWORD:	SKIPN	T1,R.WORD(R)	;IS THERE ANY MAGIC WORD HERE?
	RET			;NO, SAY NOTHING
	CALL	MAKWRD		;YES, GENERATE THE PHRASE
	STROUT	[ASCIZ/Scrawled on one of the walls is the phrase "/]
	STROUT	MAGTXT		;TYPE THE MAGIC PHRASE
	STROUT	[ASCIZ/".  /]	;FINISH THE TEXT
	RET			;DONE
;ROUTINE TO LOOK FOR MONSTERS.



LKMONS:	SKIPN	T4,R.MONS(R)	;ANY MONSTER IN THIS ROOM?
	RET			;NO, SAY NOTHING
	STROUT	[ASCIZ/This room is guarded by /]	;START TEXT
	STROUT	@MONTXT(T4)	;OUTPUT IT
	STROUT	[ASCIZ/!!!  /]	;MORE
	RET			;DONE


LKDEAD:	SKIPG	T4,R.DIES(R)	;SEE IF ANY DEATHS HERE
	JRST	MONDED		;NOT US, SEE IF MONSTERS
	STROUT	[ASCIZ/Laying here /]	;START OUT
	CAIN	T4,1		;ONE?
	STROUT	[ASCIZ/is the skeleton of an unlucky explorer.  /]	;YES
	CAIN	T4,1		;WELL?
	JRST	MONDED		;YES, SKIP ON
	STROUT	[ASCIZ/are the skeletons of /]	;NO
	DECOUT	T4		;TYPE NUMBER
	STROUT	[ASCIZ/ unlucky explorers.  /]	;FINISH

MONDED:	SKIPG	T4,R.MONK(R)	;ARE THERE ANY DEAD MONSTERS?
	RET			;NO, RETURN
	STROUT	[ASCIZ/The remains of /]	;START TEXT
	CAIN	T4,1		;ONE?
	STROUT	[ASCIZ/a monster/]	;YES
	CAIN	T4,2		;TWO?
	STROUT	[ASCIZ/a couple of monsters/]	;YES
	CAILE	T4,2		;3 OR MORE?
	DECOUT	T4		;YES, SAY HOW MANY
	CAILE	T4,2		;WELL?
	STROUT	[ASCIZ/ monsters/]	;YES, MORE OUTOUT
	STROUT	[ASCIZ/ are in this room.  /]	;FINISH IT
	RET			;DONE
;ROUTINE TO LOOK FOR MAGIC ITEMS IN THE ROOM.




LKITEM:	SKIPN	R.MONS(R)	;ANY MONSTERS IN THE ROOM?
	SKIPN	R.VITM(R)	;OR NO ITEMS IN THE ROOM?
	RET			;YES, DONE
	STROUT	[ASCIZ/Laying on the floor is /]	;START OUT
	SETZM	LISOLD		;INITIALIZE LIST
	MOVEI	T1,ITMNUM-1	;GET READY FOR LOOP
	MOVEM	T1,ITMCNT	;INITIALIZE COUNTER

ITMTEL:	CALL	GETITR		;SEE IF THE ROOM HAS ANY OF THESE
	JUMPE	T2,ITMTEX	;NO, SKIP ON
	HRLZ	T1,ITMCNT	;YES, REMEMBER TYPE
	IORI	T1,ITMTYP	;AND ADDRESS OF ROUTINE TO TYPE IT
	CALL	DOLIST		;DO THE LIST
ITMTEX:	SOSL	T1,ITMCNT	;MORE ITEMS TO TELL ABOUT?
	JRST	ITMTEL		;YES, DO SO
	CALL	DOLISE		;FINISH THE LIST
	SKIPN	LISCNT		;ANY ITEMS ACTUALLY FOUND?
	STROUT	[ASCIZ/nothing (somebody just took stuff)/]	;NO!!
	STROUT	[ASCIZ/!!!
/]				;FINISH TEXT
	RET			;DONE


ITMTYP:	MOVE	T4,T1		;SAVE TYPE OF ITEM
	HRRZ	T1,ITMTAB(T4)	;GET ADDRESS OF TEXT
	CALL	TTYSTR		;TYPE IT
	MOVE	T1,T4		;GET BACK TYPE
	CALL	GETITR		;READ NUMBER OF THEM
	CAIN	T2,1		;ONLY 1?
	RET			;YES, DONE
	MOVE	T4,T2		;SAVE NUMBER OF THEM
	STROUT	[ASCIZ/ (/]	;START OUTPUT
	SKIPN	T4		;NONE?
	STROUT	[ASCIZ/which has just been taken!)/]	;NO, SAY THIS
	SKIPE	T1,T4		;GET COUNT BACK
	CALL	TTYDEC		;OUTPUT NUMBER
	SKIPE	T4		;WELL?
	STROUT	[ASCIZ/ of them)/]	;FINISH
	RET			;DONE
	SUBTTL	SUBROUTINE TO BUILD MORE OF THE DUNGEON




;CALLED WHENEVER AN ATTEMPT IS MADE TO TRAVERSE A PASSAGEWAY
;WHICH GOES TO A NONEXISTANT ROOM.  FIRST A SEARCH IS MADE FOR A
;NEARBY ROOM THAT THIS ROOM CAN CONNECT TO.  IF THE SEARCH FAILS,
;AN ATTEMPT IS MADE TO CREATE A NEW ROOM.  CALL IS:
;
;	R/	ADDRESS OF CURRENT ROOM
;	T1/	DIRECTION TO BUILD FROM
;
;RETURNS:
;  +1:	CANNOT BUILD A ROOM FROM HERE
;  +2:	ROOM BUILT, LINK WORDS CONNECT THE ROOMS





BUILD:	MOVEM	T1,BLDDIR	;REMEMBER THE DIRECTION TO BUILD IN
	ADDI	T1,R.DIRS(R)	;GET ADDRESS OF CURRENT LINK WORD
	MOVEM	T1,BLDLNK	;REMEMBER IT
	LDB	T2,[POINTR @BLDLNK,DR%TYP]	;GET TYPE OF DOOR TO BUILD FROM
	MOVEM	T2,BLDTYP	;REMEMBER TYPE OF DOOR BUILDING FROM
	MOVE	T1,BLDDIR	;GET BACK DIRECTION TO SEARCH IN
	CAIE	T2,DR.LVL	;ALWAYS BUILD NEW ROOMS FOR LEVEL DOORS
	CALL	LNKSRC		;LOOK FOR A ROOM TO HOOK UP TO
	 JRST	NEWROM		;NONE THERE, GO TRY TO BUILD ONE

OLDROM:	MOVE	T4,BLDTYP	;GET DOOR TYPE READY
	MOVE	T1,BLDDIR	;GET DIRECTION WE BUILT FROM
	XORI	T1,1		;REVERSE THE DIRECTION SINCE FROM OTHER ROOM
	ADDI	T1,R.DIRS(S)	;GET ADDRESS OF OTHER ROOM'S LINK WORD
	MOVE	T2,@BLDLNK	;GET LINK FROM CURRENT ROOM
	MOVE	T3,(T1)		;AND LINK FROM OTHER ROOM
	TXNN	T3,DR%TYP	;A NEW PASSAGEWAY?
	DPB	T4,[POINTR T3,DR%TYP]	;YES, INSERT THE ROOM TYPE
	HRR	T2,R.ROOM(S)	;POINT CURRENT ROOM AT NEW ROOM
	HRR	T3,R.ROOM(R)	;AND POINT NEW ROOM BACK AT THIS ROOM
	MOVEM	T2,@BLDLNK	;STORE LINK WORD INTO CURRENT ROOM
	EXCH	T3,(T1)		;AND ALSO STORE LINK WORD INTO NEW ROOM
	CAIE	T4,DR.ALW	;NORMAL KIND OF DOOR?
	CAIN	T4,DR.SRC	;OR A SECRET DOOR?
	SKIPA	T1,H.LEVL	;YES, GET HIGHEST LEVEL READY
	JRST	CPOPJ1		;NO, ALL DONE
	CAMN	T1,R.LEVL(R)	;REMOVED A DOOR FROM THIS LEVEL?
	SOS	H.LGRW		;YES, REDUCE GROWTH COUNT
	JUMPE	T3,CPOPJ1	;IF WAS A NULL LINK, JUST RETURN
	CAMN	T1,R.LEVL(S)	;REMOVED ANOTHER DOOR FROM THIS LEVEL?
	SOS	H.LGRW		;YES, REDUCE GROWTH COUNT MORE
	JRST	CPOPJ1		;SUCCESSFUL RETURN
;HERE WHEN NO OLD ROOM WILL SUFFICE.  TRY TO CREATE A NEW ROOM SOMEPLACE
;THAT IS ACCEPTABLE.  T1 IS NONZERO IF SOMEPLACE NICE IS KNOWN.



NEWROM:	LDB	T2,[POINTR @BLDLNK,DR%TYP]	;GET TYPE OF DOOR FROM HERE
	CAIE	T2,DR.ALW	;ALWAYS TRAVELABLE?
	CAIN	T2,DR.SRC	;OR IS SO IF SEARCHING?
	JRST	NWHERE		;YES, RANDOMNESS IS NOT ALLOWED
	MOVE	T1,R.LEVL(R)	;GET CURRENT LEVEL NUMBER
	CAIN	T2,DR.LVL	;A CHANGE OF LEVEL DOOR?
	ADDI	T1,1		;YES, CHANGE LEVEL
	MOVEM	T1,BLDLVL	;SAVE LEVEL NUMBER FOR LATER

NWRAND:	MOVEI	T1,<MID-MIN>*2+1	;GET READY
	CALL	RANDOM		;COMPUTE A RANDOM COORDINATE
	ADDI	T1,MIN		;SOMEPLACE IN X DIRECTION
	PUSH	P,T1		;SAVE IT FOR AWHILE
	MOVEI	T1,<MID-MIN>*2+1	;DO IT AGAIN
	CALL	RANDOM		;FOR OTHER DIRECTION
	ADDI	T1,MIN		;FINISH IT
	POP	P,T2		;RESTORE OTHER COORDINATE
	HRL	T1,T2		;PUT THEM TOGETHER
	MOVE	T2,BLDLVL	;GET LEVEL TO BUILD ON
	CALL	SRCROM		;SEE IF A ROOM IS ALREADY THERE
	 SKIPA			;NO, ALL IS OK
	JRST	NWRAND		;YEP, HAVE TO TRY ANOTHER COORDINATE
	CALL	MAKROM		;TRY TO MAKE A NEW ROOM HERE
	 RET			;NO MORE SPACE
	JRST	OLDROM		;OK, NOW PROCEED TO LINK IT IN



NWHERE:	JUMPE	T1,CPOPJ	;FAIL IF ROOM WAS ALREADY HERE
	MOVE	T2,R.LEVL(R)	;GET CURRENT LEVEL
	CALL	MAKROM		;BUILD A NEW ROOM HERE
	 RET			;FAILED
	JRST	OLDROM		;OK, GO LINK IT IN
	SUBTTL	SUBROUTINE TO FIND A ROOM TO BUILD A PASSAGE TO




;THIS ROUTINE IS CALLED TO SEARCH FOR A PREVIOUSLY EXISTING ROOM WHICH
;WE CAN BUILD A PASSAGE TO.  SUCH A ROOM HAS TO HAVE A NONEXISTANT
;ROOM POINTED TO BY A LINK WORD OPPOSITE THE GIVEN DIRECTION.
;CALL:
;	R/	POINTER TO CURRENT ROOM
;	T1/	DIRECTION TO BUILD ROOM IN
;RETURNS:
;  +1:	T1/	PLACE A ROOM CAN BE BUILT IF NONZERO
;  +2:	S/	ADDRESS OF ROOM THAT CAN BE LINKED TO



LNKSRC:	MOVEM	T1,TGTDIR	;SAVE DIRECTION TO MOVE
	ADDI	T1,R.DIRS(R)	;GET ADDRESS OF THIS DIRECTION'S LINK
	LDB	T1,[POINTR 0(T1),DR%TYP]	;GET TYPE OF DOOR TO MATCH UP
	MOVEM	T1,TGTTYP	;SAVE TYPE OF DOOR TO LOOK FOR
	MOVE	T1,R.LOC(R)	;GET COORDINATES OF CURRENT ROOM
	MOVE	T2,TGTDIR	;AND DIRECTION TO SHIFT TOWARDS
	CALL	SHIFT		;GENERATE COORDINATES IN RIGHT AREA
	MOVEM	T1,TGTLOC	;REMEMBER FOR LATER
	MOVE	T2,R.LEVL(R)	;GET CURRENT LEVEL
	MOVEI	T3,CONMAX	;RANGE FOR SEARCH ALSO
	SETZB	S,TGTMAT	;GET READY AND CLEAR MATCH FOUND FLAG
	SETZM	TGTNMT		;AND CLEAR NON-TARGET MATCH FLAG

LNKSRL:	CALL	SRCRON		;FIND ANOTHER ROOM WITHIN RANGE
	  JRST	LNKSRD		;ALL DONE LOOKING
	MOVE	T4,R.LOC(S)	;GET LOCATION OF THIS ROOM
	CAMN	T4,TGTLOC	;IS IT AT EXACTLY THE RIGHT PLACE?
	MOVEM	S,TGTMAT	;YES, REMEMBER FOR LATER
	MOVE	T4,TGTDIR	;GET DIRECTION
	XORI	T4,1		;FLIP SINCE LOOKING FROM THAT ROOM
	ADDI	T4,R.DIRS(S)	;GET ADDRESS OF LINK WORD
	MOVE	T4,(T4)		;GET THE LINK WORD
	TXC	T4,DR%NXT	;COMPLEMENT BITS
	TXNE	T4,DR%NXT	;DOES LINK POINT TO NONEXISTANT ROOM?
	JRST	LNKSRL		;NO, TRY NEXT ROOM
	LDB	T4,[POINTR T4,DR%TYP]	;YES, GET DOOR TYPE
	CAME	T4,TGTTYP	;IS THIS THE TYPE WE WANT?
	JRST	LNKSRL		;NO, TRY NEXT ROOM
	MOVE	T4,R.LOC(S)	;GET LOCATION AGAIN
	CAMN	T4,TGTLOC	;EXACTLY AT RIGHT PLACE?
	JRST	CPOPJ1		;YES, RETURN THIS ROOM THEN
	MOVEM	S,TGTNMT	;NO, THEN REMEMBER AN OK ROOM
	JRST	LNKSRL		;AND LOOK FOR A BETTER ONE


LNKSRD:	SKIPE	S,TGTNMT	;WAS THERE A ROOM NEARBY WE CAN USE?
	JRST	CPOPJ1		;YES, RETURN IT
	SKIPE	TGTMAT		;WAS THERE A ROOM AT OUR EXACT COORDINATE?
	TDZA	T1,T1		;YES, SAY THERE WAS A ROOM THERE
	MOVE	T1,TGTLOC	;NO, RETURN THE ADDRESS OF THE HOLE THEN
	RET			;FAIL RETURN
	SUBTTL	SUBROUTINE TO DECIDE WHAT KIND OF DOORS TO CREATE





;CALLED WHENEVER A ROOM IS ENTERED, TO CHECK ALL DIRECTIONS FROM THE
;ROOM, AND DECIDE WHAT KIND OF DOORS THIS ROOM WILL HAVE.  DIRECTIONS
;WHICH ALREADY HAVE A DOORWAY SET ARE NOT CHANGED.  ANY DOORS BUILT
;WILL BE CLOSED.  ANY LINKS TO ROOMS WILL BE TO NONEXISTANT ROOMS.
;CALL:
;	R/	ADDRESS OF ROOM TO MAKE DOORS OF
;RETURNS:
; +1:	ALWAYS, WITH DOORS CREATED




MAKDOR:	MOVEI	T1,DIRMAX	;GET READY
	MOVEM	T1,DORDIC	;SAVE COUNT OF DIRECTIONS
	CALL	RANDOM		;PICK A STARTING DIRECTION AT RANDOM
	MOVEM	T1,DORDIR	;INITIALIZE IT


DORLOP:	SOSGE	DORDIC		;MORE DIRECTIONS TO EXAMINE?
	RET			;NO, DONE
	AOS	T1,DORDIR	;MOVE TO NEXT DIRECTION
	CAIL	T1,DIRMAX	;RAN OFF THE END?
	SETZB	T1,DORDIR	;YES, WRAP AROUND
	ADDI	T1,R.DIRS(R)	;GET ADDRESS OF THE LINK WORD
	SKIPE	(T1)		;HAS THIS DOOR BEEN CHOSEN YET?
	JRST	DORLOP		;YES, TRY NEXT ONE
	MOVSI	I,-DORNUM	;GET READY FOR A LOOP
	SETZM	CHCTOT		;CLEAR TOTAL CHANCE COUNTER

CHCLOP:	CALL	@CHCDSP(I)	;SEE WHAT CHANCE THIS DOOR SHOULD GET
	JUMPL	T1,CHCHAV	;NEGATIVE MEANS PICK IT NOW!
	MOVEM	T1,CHCTAB(I)	;REMEMBER FOR LATER
	ADDB	T1,CHCTOT	;AND ADD INTO TOTAL CHANCES
	AOBJN	I,CHCLOP	;LOOP OVER ALL TYPE OF DOORS
	CALL	RANDOM		;PICK A RANDOM NUMBER
	MOVSI	I,-DORNUM	;GET READY FOR LOOPING
	SUB	T1,CHCTAB(I)	;SUBTRACT WORTH OF THIS ROOM
	JUMPLE	T1,CHCHAV	;IF WENT NEGATIVE, HAVE ANSWER
	AOBJN	I,.-2		;KEEP GOING UNTIL GET IT
	FATAL	(Random door selection failed)

CHCHAV:	MOVX	T1,DR%NXT	;GET POINTER TO NONEXISTANT ROOM
	DPB	I,[POINTR T1,DR%TYP]	;AND STORE TYPE CODE
	MOVE	T2,DORDIR	;GRAB DIRECTION
	ADDI	T2,R.DIRS(R)	;CREATE ADDRESS OF LINK WORD
	MOVEM	T1,(T2)		;SET THIS DOOR
	MOVE	T1,R.LEVL(R)	;GET LEVEL OF THIS ROOM
	CAME	T1,H.LEVL	;IS THIS IN THE LOWEST LEVEL?
	JRST	DORLOP		;NO, JUST LOOP
	ANDX	I,DR%NXT	;KEEP ONLY THE DOOR TYPE
	CAIE	I,DR.ALW	;A NORMAL PASSAGE?
	CAIN	I,DR.SRC	;OR A SECRET PASSAGE?
	AOS	H.LGRW		;YES, INCREMENT GROWTH POTENTIAL
	CAIN	I,DR.LVL	;IS THIS A LEVEL CHANGE DOOR?
	AOS	H.LDOR		;YES, COUNT THEM UP
	JRST	DORLOP		;LOOP SOME MORE
;DISPATCH TABLE FOR VARIOUS TYPES OF DOOR CHANCES.  THE COMPUTED
;CHANCE (WHERE ^D1000 IS "NORMAL") IS RETURNED IN T1.  IF NEGATIVE,
;THEN THAT TYPE OR DOOR IS TO BE SELECTED OVER ALL OTHERS.


CHCDSP:	EXP	CHCUNK		;(0) UNKNOWN
	EXP	CHCNEV		;(1) NEVER
	EXP	CHCALW		;(2) ALWAYS
	EXP	CHCSRC		;(3) SECRET
	EXP	CHCLVL		;(4) LEVEL CHANGE
	EXP	CHCWRD		;(5) MAGIC WORD
	EXP	CHCMAG		;(6) MAGIC ITEM
	EXP	CHCBLK		;(7) CAVE IN

	DORNUM==.-CHCDSP	;NUMBER OF DOORS TO SELECT FROM




;HERE TO SEE HOW MUCH WE WANT A WALL (IE, NO PASSAGE):


CHCNEV:	MOVEI	T1,^D1000	;GET STANDARD CHANCE
	RET			;DONE




;HERE TO SEE HOW MUCH WE WANT A LEVEL-CHANGE DOOR:


CHCLVL:	MOVEI	T1,^D25		;GET A VERY SMALL CHANCE
	SKIPE	H.LDOR		;ALREADY HAVE A LEVEL CHANGE DOOR?
	RET			;YES, DON'T WANT MORE EASILY
	SETO	T1,		;GET INFINITE CHANCE
	MOVE	T2,H.LGRW	;AND NUMBER OF GROWING DOORS ON THIS LEVEL
	SOJLE	T2,CPOPJ	;IF ON LAST DOOR, MAKE THIS KIND!!
	MOVE	T1,H.LROM	;GET NUMBER OF ROOMS IN THIS LEVEL
	CAMGE	T1,H.LDWN	;CREATED ENOUGH ROOMS IN THE LEVEL YET?
	TDZA	T1,T1		;NO, DON'T ALLOW THESE YET
	MOVEI	T1,^D500	;YES, GET LARGE CHANCE
	RET			;DONE
;HERE TO SEE HOW MUCH WE WANT A NORMAL PASSAGEWAY:


CHCALW:	MOVEI	T1,^D400	;GET A CHANCE THAT WILL CLOSE OFF EVENTUALLY
	MOVE	T2,R.LEVL(R)	;GRAB THIS ROOM'S LEVEL
	CAMGE	T2,H.LEVL	;IN THE LOWEST LEVEL?
	RET			;NO, USE THIS CHANCE
	MOVE	T2,H.LGRW	;GET NUMBER OF GROWING REGIONS
	CAILE	T2,^D20		;ENOUGH TO PLAY WITH?
	RET			;YES, RETURN
	MOVEI	T1,^D1000	;NO, GET A MUCH LARGER CHANCE
	MOVE	T2,H.LROM	;GET NUMBER OF ROOMS IN THIS LEVEL
	CAIGE	T2,5		;LEVEL JUST STARTED?
	SETO	T1,		;YES, ALWAYS USE THIS DOOR TYPE
	RET			;DONE




;HERE TO SEE HOW MUCH WE WANT A SECRET DOORWAY:


CHCSRC:	CALL	CHCALW		;SEE HOW MUCH A NORMAL PASSAGEWAY IS WANTED
	JUMPL	T1,CHCBLK	;IF DESIRED, SAY WE DON'T WANT OUR TYPE
	IDIVI	T1,^D10		;REDUCE CHANCE BY 90% OR SO
	RET			;AND USE THAT




;HERE TO SEE HOW MUCH WE WANT MAGIC DOORS OF VARIOUS TYPES:


CHCMAG:
CHCWRD:	MOVE	T1,R.LEVL(R)	;GET LEVEL OF THIS ROOM
	IMULI	T1,^D5		;MULTIPLY BY NICE CHANCE
	CAILE	T1,^D50		;GETTING RATHER HIGH?
	MOVEI	T1,^D50		;YES, REDUCE TO MAXIMUM
	RET			;DONE




;HERE FOR DOOR TYPES WE NEVER WANT TO SELECT:


CHCUNK:
CHCBLK:	SETZ	T1,		;THESE NEVER HAPPEN
	RET			;DONE
	SUBTTL	SUBROUTINE TO PUT TREASURE IN A ROOM





;CALLED TO POPULATE A ROOM WITH TREASURE WHEN NECESSARY.  THE AMOUNT
;OF TREASURE INCREASES WITH LEVEL NUMBER, THE LENGTH OF A DEAD END,
;AND WHETHER OR NOT SECRET DOORS HIDE IT.  CALL:
;
;  	R/	ADDRESS OF ROOM TO MAKE TREASURE FOR
;
;RETURNS:
;   +1:	ALWAYS, WITH R.VTRE AND R.HTRE UPDATED IF NECESSARY




MAKTRE:	SKIPN	R.VTRE(R)	;ANY TREASURE IN ROOM ALREADY?
	SKIPE	R.HTRE(R)	;WELL?
	RET			;YES, DON'T MAKE ANY MORE
	TDNN	ZR,R.ROOM(R)	;AT THE ENTRANCE?
	RET			;YES, NO TREASURE FOR THERE
	MOVEI	T1,R.TREF(R)	;POINT TO TREASURE FINDING WORD
	CALL	BITSET		;COMPUTE OFFSET AND BIT
	TDNE	T2,(T1)		;TRIED TO GET TREASURE HERE BEFORE?
	RET			;YES, CAN'T GET ANY MORE HERE
	MOVEI	T1,DR.NEV	;GET NONEXISTANT TYPE CODE
	CALL	FNDDOR		;SEE HOW MANY THERE ARE
	MOVEM	T1,TRETMP	;SAVE FOR AWHILE
	MOVEI	T1,DR.BLK	;GET CAVED-IN DOOR TYPE
	CALL	FNDDOR		;SEE HOW MANY OF THEM EXIST
	ADD	T1,TRETMP	;GET TOTAL NUMBER
	CAIGE	T1,DIRMAX-1	;IS THIS ROOM A DEAD END?
	SKIPA	T1,[^D25]	;NO, GET VERY SMALL CHANCE
	MOVEI	T1,3		;YES, GET MUCH BETTER CHANCE
	MOVE	T2,R.VIST(R)	;GET NUMBER OF VISITS
	CAILE	T2,1		;ARE WE THE FIRST VISITOR TO ROOM?
	ADDI	T1,1		;NO, REDUCE CHANCE OF TREASURE A BIT
	CALL	RANDOM		;COMPUTE RANDOMNESS
	JUMPN	T1,TRENOM	;JUMP IF NEVER FIND TREASURE HERE
	MOVEI	T1,DR.SRC	;WE FIND TREASURE, GET READY
	CALL	FNDDOR		;SEE IF THERE IS A HIDDEN ROOM
	MOVEM	T1,TRETMP	;SAVE RESULT
	HRRZ	T1,R.LEVL(R)	;GET LEVEL OF THIS ROOM
	IMULI	T1,^D100	;MULTIPLY BY CONSTANT
	CALL	RANDOM		;GET A RANDOM NUMBER
	AOS	T4,T1		;MOVE AND ALWAYS MAKE NONZERO
	SKIPE	TRETMP		;IS THIS ROOM HIDDEN BY A SECRET DOOR?
	ADDI	T4,^D100	;YES, INCREASE THE BOOTY
	MOVEI	T1,^D10		;GET SET TO DECIDE ON 10% CHANCE
	CALL	RANDOM		;MAKE A RANDOM NUMBER
	SKIPE	T1		;VISIBLE TREASURE WANTED?
	ADDM	T4,R.VTRE(R)	;YES, ADD TO IT
	ADDI	T4,^D100	;HIDDEN TREASURE GETS MORE
	SKIPN	T1		;INVISIBLE TREASURE WANTED?
	ADDM	T4,R.HTRE(R)	;YES, ADD TO IT
TRENOM:	MOVEI	T1,R.TREF(R)	;POINT TO TREASURE FLAGS
	CALL	BITSET		;MAKE OFFSET AND BIT
	IORM	T2,(T1)		;SAY WE GET NO MORE TREASURE HERE
	RET			;DONE
	SUBTTL	SUBROUTINE TO MAKE A MAGICAL ITEM





;CALLED WHEN WE ENTER A ROOM, TO GENERATE A MAGICAL ITEM FOR THAT ROOM.
;ONLY ONE MAGICAL ITEM CAN BE FOUND FOR EACH LEVEL IN THE DUNGEON FOR
;EACH PLAYER, SO THAT IT IS HARD TO COLLECT ALL OF THEM.  THE FIRST
;ITEM FOUND WILL BE THE FIRST MAGIC WAND, SO THAT SOME OF THE MAGIC
;DOORS CAN BE OPENED.  AFTER THAT, THEY APPEAR RANDOMLY.



MAKITM:	TDNE	ZR,R.ROOM(R)	;IS THIS THE ENTRANCE?
	SKIPE	R.VITM(R)	;OR THE ROOM ALREADY HAS ITEMS?
	RET			;YES, NO ITEMS TO MAKE
	MOVE	T1,R.LEVL(R)	;GET CURRENT LEVEL
	MOVEI	T4,1		;AND A BIT
	LSH	T4,(T1)		;SHIFT IT
	JUMPE	T4,CPOPJ	;TOO LOW FOR MAGIC ITEMS!!
	TDNE	T4,U.ITEL(U)	;HAVE AN ITEM ALREADY FROM THIS LEVEL?
	RET			;YES, NO MORE FOR YOU!!
	MOVEI	T1,^D50		;GET A CHANCE
	CALL	RANDOM		;TO SEE IF WE FIND IT YET
	JUMPN	T1,CPOPJ	;NO, RETURN
	MOVEI	T1,ITMNUM	;GET READY
	SKIPN	U.ITEL(U)	;GOTTEN SOMETHING BEFORE?
	SKIPA	T1,[EXP	IT.WD1]	;NO, THEN GET A MAGIC WAND
	CALL	RANDOM		;OTHERWISE COMPUTE A RANDOM OBJECT
	MOVEI	T3,^D200	;GET FAILSAFE COUNTER


ITMTRY:	CALL	GETITU		;SEE IF WE HAVE ANY OF THIS ITEM YET
	JUMPE	T2,ITMBLD	;NO, GO MAKE US ONE
	MOVEI	T1,ITMNUM	;YES, GET READY
	CALL	RANDOM		;PICK ANOTHER MAGIC ITEM
	SOJG	T3,ITMTRY	;AND TRY TO USE IT
	IORM	T4,U.ITEL(U)	;SOMETHING IS WRONG, RIP HIM OFF
	RET			;AND RETURN


ITMBLD:	MOVEI	T2,1		;WANT ONE ITEM
	CALL	PUTITR		;PLACE IT IN THE ROOM
	IORM	T4,U.ITEL(U)	;THAT'S ALL FROM THIS LEVEL
	RET			;DONE
	SUBTTL	SUBROUTINE TO CREATE A MONSTER IN A ROOM




;CALLED WHENEVER WE MOVE INTO A ROOM, TO CREATE A NEW MONSTER HERE
;IF THE CONDITIONS ARE RIGHT.  CALL:
;	R/	ADDRESS OF CURRENT ROOM
;	T1/	MULTIPLY-CONNECTED-CHANCE,,SINGLEY-CONNECTED-CHANCE



MAKMON:	SKIPE	R.MONS(R)	;ALREADY A MONSTER HERE?
	RET			;YES, DO NOTHING
	HRRZ	T2,R.ROOM(R)	;GET ROOM NUMBER
	CAIGE	T2,^D20		;ONE OF THE REAL EARLY ROOMS?
	RET			;YES, NO MONSTERS YET
	PUSH	P,T1		;SAVE CHANCE
	MOVEI	T1,DR.NEV	;GET NONEXISTANT TYPE CODE
	CALL	FNDDOR		;SEE HOW MANY THERE ARE
	MOVEM	T1,TRETMP	;SAVE FOR AWHILE
	MOVEI	T1,DR.BLK	;GET CAVED-IN DOOR TYPE
	CALL	FNDDOR		;SEE HOW MANY OF THEM EXIST
	ADD	T1,TRETMP	;GET TOTAL NUMBER
	POP	P,T2		;RESTORE CHANCES
	CAILE	T1,DIRMAX-3	;IS THIS ROOM MULTIPLY CONNECTED?
	SKIPA	T1,T2		;NO, GET ONE CHANCE
	MOVS	T1,T2		;YES, GET OTHER CHANCE
	ANDI	T1,-1		;CLEAR LEFT HALF
	CALL	RANDOM		;COMPUTE RANDOM NUMBER
	JUMPN	T1,CPOPJ	;RETURN IF NOT TIME FOR A MONSTER
	MOVEI	T4,^D100	;MAXIMUM TRIES IN CASE OF A BUG

MONSRC:	SOJLE	T4,CPOPJ	;FAIL IF TRIED TOO MUCH
	MOVEI	T1,MONNUM	;GET NUMBER OF MONSTERS
	CALL	RANDOM		;PICK ONE AT RANDOM
	HLRZ	T2,MONPWR(T1)	;GET STRENGTH OF MONSTER
	ADD	T2,MONPWR(T1)	;WHICH IS SUM OF ATTACK AND DEFENSE
	ANDI	T2,-1		;KEEP ONLY RIGHT HALF
	IDIVI	T2,3		;GET WHAT "LEVEL" THIS MONSTER IS
	CAMLE	T2,R.LEVL(R)	;ARE WE DOWN TO THAT LEVEL YET?
	JRST	MONSRC		;NO, DON'T USE THIS MEAN MONSTER
	ADDI	T2,^D10		;ADD 10 LEVELS
	CAMGE	T2,R.LEVL(R)	;MONSTER TOO WIMPY FOR THIS LEVEL?
	JRST	MONSRC		;YES, DON'T USE IT
	MOVE	T4,T1		;PUT INDEX IN SAFE AC
	HLRZ	T3,MONPWR(T4)	;GET MAXIMUM STRENGTH OF MONSTER
	LSH	T3,1		;HALF IT
	MOVE	T1,T3		;PUT IN RIGHT AC
	CALL	RANDOM		;RANDOMIZE IT
	ADD	T1,T3		;ADD IN HALF STRENGTH ALSO
	MOVE	T2,R.LEVL(R)	;GET LEVEL
	SUBI	T2,1		;DECREMENT
	IMULI	T2,3		;MULTIPLY BY A CONSTANT
	ADD	T1,T2		;MAKE IT STRONGER!
	MOVEM	T1,R.MONH(R)	;SAVE STRENGTH OF THE MONSTER
	HRROM	T4,R.MONS(R)	;SAY A MONSTER EXISTS NOW
	AOS	H.MONS		;INCREMENT NUMBER OF MONSTERS IN DUNGEON
	RET			;DONE
	SUBTTL	SUBROUTINE TO ALLOCATE A NEW ROOM




;CALLED TO FIND THE NEXT FREE LOCATION IN THE DATA FILE, AND ALLOCATE
;A NEW ROOM.  THE ROOM IS LEFT EMPTY, WITH NO LINKS TO ANY OTHER ROOM.
;ACCEPTS:
;	T1/	COORDINATES WHERE THIS ROOM IS
;	T2/	LEVEL THIS ROOM IS ON
;
;RETURNS:
; +1:	UNABLE TO MAKE A NEW ROOM
; +2:	S/	ADDRESS OF THIS ROOM'S DATA BLOCK




MAKROM:	MOVE	S,H.ROOM	;GET NEXT AVAILABLE ROOM NUMBER
	IMULI	S,ROMSIZ	;THEN COMPUTE OFFSET INTO ROOM DATA
	ADDI	S,ROMADR	;AND RELOCATE TO CORRECT ADDRESS
	CAIL	S,MAPLST-ROMSIZ-2	;ROOM FOR A NEW ROOM?
	RET			;NO, ERROR RETURN
	MOVSI	T3,0(S)		;GET READY TO CLEAR THE DATA
	IORI	T3,1(S)		;BEFORE USING IT
	SETZM	0(S)		;CLEAR FIRST WORD
	 ERJMP	CPOPJ		;NO MORE DISK, FAIL RETURN
	BLT	T3,ROMSIZ-1(S)	;THEN THE REST
	 ERJMP	CPOPJ		;NO DISK, FAIL
	MOVEM	T1,R.LOC(S)	;SET WHERE THIS ROOM IS
	MOVEM	T2,R.LEVL(S)	;AND WHAT LEVEL IT IS ON
	MOVE	T3,H.ROOM	;GET ROOM NUMBER
	HRROM	T3,R.ROOM(S)	;AND SET IT
	SETOM	R.FVIS(S)	;CLEAR WHO FIRST VISITED ROOM
	SETOM	R.LVIS(S)	;AND WHO LAST VISITED ROOM
	AOS	H.ROOM		;INCREMENT NUMBER OF ROOMS TOTAL
	CAMG	T2,H.LEVL	;IS THIS A LOWER LEVEL THAN PREVIOUSLY?
	JRST	MAKRM2		;NO, SKIP ON
	MOVEM	T2,H.LEVL	;YES, SET NEW LOWEST LEVEL
	SETZM	H.LROM		;CLEAR NUMBER OF ROOMS IN THIS LEVEL
	SETZM	H.LDOR		;AND NUMBER OF LEVEL CHANGE DOORS
	SETZM	H.LGRW		;INITIALIZE GROWABLE DOORS TOO
	SETZM	H.LLUK		;NO LUCKY ROOM YET
	MOVEI	T1,^D200	;GET NICE NUMBER
	CALL	RANDOM		;RANDOMIZE IT SOME
	ADDI	T1,^D200	;SHIFT SO IS IN RANGE 200-400
	MOVEM	T1,H.LDWN	;SET ROOMS NEEDED BEFORE LEVEL-CHANCE IS DONE
	MOVE	T2,H.LEVL	;RESTORE T2
MAKRM2:	CAMN	T2,H.LEVL	;BUILDING A ROOM ON THE LOWEST LEVEL?
	AOS	H.LROM		;YES, BUMP COUNT OF ROOMS THERE
	TDNN	ZR,R.ROOM(S)	;ENTRANCE ROOM?
	JRST	CPOPJ1		;YES, NO MAGIC WORDS HERE
	MOVEI	T1,^D20		;OTHERWISE GET A CHANCE
	CALL	RANDOM		;SEE IF WE NEED A MAGIC WORD HERE
	JUMPN	T1,CPOPJ1	;NO, GOOD RETURN
	MOVE	T1,H.WORD	;GET NUMBER OF MAGIC WORDS IN USE
	CAIGE	T1,WRDMAX	;REACHED THE MAXIMUM?
	AOSA	H.WORD		;NO, INCREMENT NUMBER IN USE
	CALL	RANDOM		;YES, GENERATE RANDOM ONE
	ADDI	T1,1		;COMPENSATE FOR WORD 0 WHICH ISN'T USED
	MOVEM	T1,R.WORD(S)	;REMEMBER WHICH WORD IS IN ROOM
	JRST	CPOPJ1		;GOOD RETURN
	SUBTTL	SUBROUTINE TO SEARCH FOR ROOMS




;CALLED TO LOOK FOR THE NEXT ROOM MATCHING THE GIVEN CONDITIONS,
;AND RETURN THE ADDRESS OF IT'S DATA.  CALL:
;
;	T1/	ADDRESS TO SEARCH AROUND
;	T2/	LEVEL OF ROOM
;	T3/	RANGE FOR SEARCHING
;	S/	LAST ROOM EXAMINED, OR 0
;
;RETURNS:
;
;	+1:	ROOM NOT EXISTANT
;	+2:	ROOM FOUND, ADDRESS IN AC S
;
;AC'S T1-T3 ARE PRESERVED.  CALL SRCROM TO SEARCH FOR JUST ONE ROOM,
;SRCRON TO SEARCH WITH A RANGE.



SRCROM:	SETZB	T3,S		;RANGE OF ZERO, AND NONE KNOWN YET
SRCRON:	SKIPN	S		;WANT TO START AT THE BEGINNING?
	MOVEI	S,ROMADR-ROMSIZ	;YES, SET IT UP
	MOVE	T4,H.ROOM	;GET NUMBER OF ROOMS
	IMULI	T4,ROMSIZ	;MAKE SIZE
	ADDI	T4,ROMADR	;RELOCATE TO AN ADDRESS
	MOVEM	T4,MAXADR	;SAVE IT AWAY

SRCRLP:	ADDI	S,ROMSIZ	;ADVANCE TO THE NEXT ROOM
	CAMLE	S,MAXADR	;LOOKED AT THEM ALL YET?
	RET			;YES, WE DIDN'T FIND IT
	CAME	T2,R.LEVL(S)	;IS THIS THE CORRECT DEPTH?
	JRST	SRCRLP		;NO, SKIP THE ROOM
	CAMN	T1,R.LOC(S)	;EXACT MATCH OF COORDINATES?
	JRST	CPOPJ1		;YES, WE FOUND IT
	JUMPE	T3,SRCRLP	;GO ON IF HAS TO BE EXACT
	HLRZM	T1,TEMP		;STORE THE X COORDINATE FOR AWHILE
	HLRZ	T4,R.LOC(S)	;GET X COORDINATE OF THIS ROOM
	SUB	T4,TEMP		;GET DIFFERENCE
	MOVM	T4,T4		;KEEP ABSOLUTE VALUE
	CAMLE	T4,T3		;WITHIN RANGE?
	JRST	SRCRLP		;NO, GO TO NEXT ROOM
	HRRZM	T1,TEMP		;STORE Y COORDINATE
	HRRZ	T4,R.LOC(S)	;GET Y COORDINATE OF THIS ROOM
	SUB	T4,TEMP		;GET DIFFERENCE
	MOVM	T4,T4		;KEEP ABSOLUTE VALUE
	CAMLE	T4,T3		;WITHIN RANGE?
	JRST	SRCRLP		;NO, KEEP SEARCHING
CPOPJ1:	AOS	(P)		;WE FOUND ONE WITHIN RANGE
	RET			;DONE
	SUBTTL	SUBROUTINE TO RETURN DESIRED DOORS





;THIS SUBROUTINE SEARCHES THE CURRENT ROOM, AND RETURNS IN THE TABLE
;DORTAB WHICH DIRECTIONS HAVE A SPECIFIED TYPE OF DOOR.  THIS IS USED
;SO THAT THE OUTPUT OF WHICH KIND OF DOORS EXIST CAN BE DONE.
;CALL:
;	R/	ADDRESS OF THIS ROOM
;	T1/	DOOR TYPE
;RETURNS:
;  +1:	T1/	NUMBER OF DOORS FOUND
;	DORTAB TABLE/	-1 IF DIRECTION HAS THAT DOOR, 0 IF NOT




FNDDOR:	MOVSI	T2,-DIRMAX	;GET READY FOR LOOPING
	SETZ	T3,		;CLEAR COUNTER

FNDDOL:	HRRZ	T4,T2		;COPY DIRECTION
	ADDI	T4,R.DIRS(R)	;GET ADDRESS OF THE POINTER WORD
	LDB	T4,[POINTR 0(T4),DR%TYP]	;GET TYPE OF DOOR
	SETOM	DORTAB(T2)	;ASSUME FOUND THE DOOR
	CAMN	T1,T4		;DID WE REALLY?
	AOSA	T3		;YES, COUNT UP DIRECTIONS FOUND
	SETZM	DORTAB(T2)	;NO, CLEAR THE WORD
	AOBJN	T2,FNDDOL	;LOOP OVER ALL DIRECTIONS
	MOVE	T1,T3		;COPY COUNT
	RET			;DONE
	SUBTTL	SUBROUTINE TO MAKE HANDLING BIT TABLES EASY





;CALLED TO COMPUTE THE ADDRESS AND BIT POSITION INTO A TABLE WHICH
;IS TO BE INDEXED BY THE PLAYER NUMBER.  CALL:
;
;	T1/	ADDRESS OF START OF TABLE
;RETURNS:
;	T1/	ADDRESS WHERE BIT IS
;	T2/	BIT POSITIONED PROPERLY
;USES T1-T3




BITSET:	MOVE	T2,MYNUM	;GET WHICH PLAYER I AM
	IDIVI	T2,^D36		;SPLIT INTO OFFSET AND BIT POSITION
	ADD	T1,T2		;ADD OFFSET TO START OF TABLE
	MOVEI	T2,1		;GET THE BIT READY
	LSH	T2,(T3)		;POSITION IT TO PROPER PLACE
	RET			;DONE
	SUBTTL	SUBROUTINES TO USE FOR MAGICAL ITEMS



;THESE ROUTINES ARE CALLED TO MANIPULATE MAGICAL ITEMS.  SINCE MANY
;ITEMS ARE PACKED INTO A WORD, IT IS USEFUL TO HAVE SUBROUTINES TO
;REFERENCE THEM.




;ROUTINES TO READ THE NUMBER OF ITEMS A PARTICULAR ROOM OR PERSON
;IS CARRYING.  CALL:
;	T1/	ITEM NUMBER
;RETURNS:
;	T1/	ITEM NUMBER
;	T2/	NUMBER OF ITEMS CARRIED
;SAVES T3 AND T4.



GETITR:	SKIPA	T2,R.VITM(R)	;GET WORD FROM ROOM
GETITU:	MOVE	T2,U.ITEM(U)	;OR FROM THE PLAYER
	PUSH	P,T3		;SAVE T3
	MOVN	T3,T1		;GET NEGATIVE NUMBER
	IMULI	T3,ITMWID	;MULTIPLY BY BITS PER ITEM
	LSH	T2,(T3)		;SHIFT TO SELECT RIGHT ITEM COUNT
	ANDI	T2,ITMMSK	;CLEAR ALL OTHER STUFF
	POP	P,T3		;RESTORE AC
	RET			;RETURN COUNT



;ROUTINES TO SAVE THE NUMBER OF ITEMS A PARTICULAR ROOM OR PLAYER IS
;CARRYING.  CALL:
;	T1/	ITEM NUMBER
;	T2/	NUMBER OF ITEMS
;
;DESTROYS T2 AND T3.  IF MORE ITEMS ARE SPECIFIED THAN WILL FIT IN
;THE FIELD, THE EXCESS IS IGNORED AND THE MAXIMUM IS STORED.



PUTITR:	SKIPA	T3,[Z R.VITM(R)]	;GET POINTER TO ROOM'S ITEMS
PUTITU:	MOVE	T3,[Z U.ITEM(U)]	;OR THE USER'S ITEMS
	MOVEM	T3,TEMP		;SAVE
	TXNE	T2,ITMMSK+1	;MORE ITEMS THAN WE CAN STORE?
	MOVEI	T2,ITMMSK	;YES, USE THE MAXIMUM
	MOVEI	T3,ITMMSK	;GET MASK READY
	PUSH	P,T1		;SAVE ITEM
	IMULI	T1,ITMWID	;FINISH SHIFT VALUE
	LSH	T2,(T1)		;POSITION NEW VALUE
	LSH	T3,(T1)		;AND MASK
	ANDCAM	T3,@TEMP	;CLEAR CURRENT VALUE
	IORM	T2,@TEMP	;AND SET NEW VALUE
	POP	P,T1		;RESTORE ITEM
	RET			;DONE
	SUBTTL	ROUTINES TO HANDLE PATH MANIPULATION




;THESE SUBROUTINES ARE USED TO INSERT, DELETE, OR SEARCH FOR
;PATH DEFINITIONS.  THESE ARE STORED IN THE U.PATH AREA OF THE
;USER'S DATA BLOCK.  EACH PATH DEFINITIONS LOOKS LIKE:
;	0/	SIXBIT NAME OF PATH
;	1/	LEFT HALF:	NUMBER OF WORDS OF DIRECTION CODES
;	2/	RIGHT HALF:	FIRST FEW DIRECTION CODES
;	3-N/	MORE DIRECTION CODES
;
;THE DIRECTION CODES ARE STORED IN BYTES, AND A -1 BYTE INDICATES THE
;END OF THE LIST.  PATH DEFINITIONS FOLLOW EACH OTHER.  END OF PATHS
;IS DETERMINED BY A ZERO NAME.  LAST WORD OF TABLE IS ALWAYS ZERO.



;SUBROUTINE TO SEARCH FOR A SPECIFIED PATH.  CALL:
;	T1/	NAME OF PATH
;RETURNS:
;  +1:	NO SUCH PATH, T1/ FIRST FREE LOCATION IN TABLE
;  +2:	FOUND IT, T1/  ADDRESS OF THE PATH
;USES T2 AND T3.


PTHSRC:	MOVEM	T1,PTHTMP	;REMEMBER PATH LOOKING FOR
	MOVEI	T1,U.PATH(U)	;SET UP ADDRESS TO START AT

PTHSRL:	SKIPN	T2,0(T1)	;ANY NAME HERE?
	RET			;NO MORE, GIVE FAILURE RETURN
	HLRZ	T3,1(T1)	;GET LENGTH OF THIS PATH
	ADD	T3,T1		;COMPUTE LAST WORD OF DEFINITION
	CAME	T3,T1		;SEE IF ZERO LENGTH
	CAIL	T3,U.PATH+PTHMAX-1(U)	;OR GOING OFF OF END
	 ERROR	(,,? Size of path definition is illegal)	;YES
	CAMN	T2,PTHTMP	;IS THIS THE PATH?
	JRST	CPOPJ1		;YES, RETURN IT
	AOS	T1,T3		;NO, GET ADDRESS OF NEXT DEFINITION
	JRST	PTHSRL		;CONTINUE LOOKING
;SUBROUTINE TO DELETE A PATH DEFINITION.  CALL:
;	T1/	PATH NAME
;RETURNS:
;  +1:	ALWAYS, WITH PATH DEFINITION DELETED
;THIS IS A NO-OP IF THE PATH WAS NOT DEFINED.
;USES T1-T3.



PTHDEL:	CAMN	T1,U.PATN(U)	;DELETING THE PATH WE WERE FOLLOWING?
	SETZM	U.PATN(U)	;YES, CAN'T FOLLOW IT ANY LONGER
	CALL	PTHSRC		;LOOK FOR THE PATH FIRST
	 RET			;NOT THERE, SO NOTHING TO DO
	MOVEI	T2,U.PATH+PTHMAX-1(U)	;GET LAST ADDRESS OF DEFINITION AREA
	HLRZ	T3,1(T1)	;GET ONE LESS THAN SIZE OF BLOCK
	ADDI	T3,1		;MAKE SIZE
	SUB	T2,T3		;COMPUTE LAST WORD TO BLT TO
	ADD	T3,T1		;GET ADDRESS OF NEXT BLOCK
	HRL	T1,T3		;FINISH BLT POINTER
	BLT	T1,(T2)		;MOVE OTHER DEFINITIONS UP ON TOP OF OURS
	RET			;DONE
;SUBROUTINE TO INSERT A PATH DEFINITION.  THE PATH IS INSERTED BY SCANNING
;THE MOVLST TABLE.  ANY NEW PATH WILL DELETE THE OLD ONE.  CALL:
;	T1/	PATH NAME
;RETURNS:
;  +1:	NOT ENOUGH STORAGE LEFT FOR THIS PATH
;  +2:	NEW DEFINITION STORED, T1/  PATH NAME, T2/  ADDRESS OF DEFINITION
;USES T2-T4.



PTHADD:	MOVEM	T1,PTHNAM	;SAVE PATH TO BE CREATED
	CALL	PTHDEL		;REMOVE ANY EXISTING DEFINITION
	SETZ	T1,		;GET READY
	CALL	PTHSRC		;LOOK FOR FIRST HOLE IN TABLE
	 JFCL			;CAN RETURN EITHER WAY
	MOVEM	T1,PTHTMP	;REMEMBER WHERE WE ARE ADDING
	ADD	T1,[POINT PTHWID,1,17]	;FINISH BYTE POINTER
	MOVE	T2,[POINT PTHWID,MOVLST]	;GET OTHER ONE
	MOVEI	T3,U.PATH+PTHMAX-1(U)	;GET ADDRESS OF FIRST ILLEGAL WORD

PTHADL:	IBP	T1		;MOVE TO NEXT BYTE
	CAIG	T3,(T1)		;OVERFLOWING STORAGE?
	RET			;YES, RETURN BAD
	ILDB	T4,T2		;NO, GET NEXT DIRECTION
	DPB	T4,T1		;STORE IT
	CAIE	T4,PTHMSK	;LIST TERMINATED?
	JRST	PTHADL		;NO, GO TO NEXT ONE
	SETZM	1(T1)		;MAKE SURE NEXT WORD IS END OF TABLE
	SUB	T1,PTHTMP	;SEE HOW MANY WORDS WE USED
	MOVE	T2,PTHTMP	;GET ADDRESS OF LOCATION
	HRLM	T1,1(T2)	;STORE SIZE OF DEFINITION
	MOVE	T1,PTHNAM	;GET BACK NAME
	MOVEM	T1,0(T2)	;SET IT NOW
	JRST	CPOPJ1		;GOOD RETURN
	SUBTTL	SUBROUTINE TO INITIALIZE THE DATA FILE




;THIS PRIVILEGED COMMAND WILL ZERO OUT THE DATA FILE AND MAKE A NEW
;DUNGEON.  DOES THE "INITIALIZE" COMMAND.




CMDINI:	NOISE	(THE DUNGEON)	;DO SOME NOISE
	CONFRM			;CONFIRM THE LINE
	HRROI	T1,[ASCIZ/
WARNING:  This command will destroy the current dungeon.  Type ^C
within 15 seconds if you want to abort this command.
/]				;GET STRING
	PSOUT			;WARN HIM WHAT IS HAPPENING
	MOVEI	T1,^D15000	;GET A TIME
	DISMS			;WAIT THAT LONG
	CALL	FILCLS		;CLOSE UP THE CURRENT FILE
	CALL	FILINI		;THEN INITIALIZE THE NEW FILE
	CALL	FILOPN		;AND OPEN IT BACK UP
	TXZ	F,FR.PLY	;NO LONGER PLAYING
	TXO	F,FR.BLD	;MAKE SURE COMMANDS ARE RIGHT
	STROUT	[ASCIZ/
Done.
/]				;TYPE OUT WE DID IT
	RET			;DONE
	SUBTTL	COMMAND TO BECOME ANOTHER PLAYER




;THIS PRIVILEGED COMMAND ALLOWS THE GODLY PERSON TO CHANGE WHO HE IS
;PLAYING AS, TO MAKE DEBUGGING EASIER.



CMDBEC:	NOISE	(THE PLAYER)	;DO NOISE
	CALL	PARUSR		;READ IN THE USER NUMBER
	MOVE	T4,T2		;SAVE IT
	CONFRM			;CONFIRM THE LINE
	HRLI	T4,USRLH	;PUT IN LEFT HALF CODE
	MOVEM	T4,PLYUSR	;SET WHO WE ARE PLAYING AS
	TXZ	F,FR.PLY	;WE ARE NOT PLAYING ANYMORE
	TXO	F,FR.BLD	;HAVE TO REBUILD COMMAND TABLE
	SETZB	U,R		;NO POINTERS ARE VALID ANYMORE
	STROUT	[ASCIZ/
Done.
/]				;SAY WE ARE DONE
	RET			;RETURN
	SUBTTL	SUBROUTINE TO SEARCH DATA FILE FOR MY ENTRY




;CALLED TO SEARCH THE DATA FILE FOR MY ENTRY, AND RETURN THE OFFSET
;INTO THE FILE IN AC "U" SO MY DATA CAN BE REFERENCED.  IF I AM NOT
;CURRENTLY IN THE FILE, I WILL BE INSERTED.  DOESN'T RETURN ON ERRORS.




FINDME:	CALL	LOCK		;INTERLOCK THE FILE DATA
	MOVE	T1,PLYUSR	;GET MY USER NUMBER READY FOR SEARCHING
	CALL	FNDUSR		;LOOK FOR MY ENTRY
	 JRST	NEWPLR		;NOT FOUND, GO INSERT ME
	MOVE	U,T2		;OK, PUT ADDRESS INTO RIGHT AC
	JRST	OLDPLR		;AND GO FINISH UP

NEWPLR:	CAIL	T2,ROMADR	;ANY ROOM LEFT FOR A NEW PLAYER?
	 ERROR	(,,<Sorry, no room left for new players>)	;NO
	MOVE	U,T2		;REMEMBER ADDRESS
	MOVSI	T2,0(U)		;GET ADDRESS OF THIS ENTRY
	HRRI	T2,1(U)		;AND THE NEXT WORD
	SETZM	0(U)		;CLEAR FIRST WORD
	BLT	T2,PLRSIZ-1(U)	;THEN CLEAR REST TOO
	MOVEM	T1,U.USER(U)	;REMEMBER WHO WE ARE
	GTAD			;GET TODAY'S DATE
	MOVEM	T1,U.BDAT(U)	;REMEMBER WHEN WE ENTERED THE GAME
	MOVEM	T1,U.LDAT(U)	;AND SET WHEN LAST PLAYED TOO
	AOS	U.TURN(U)	;START US AT TURN 1
	AOS	U.LEVL(U)	;MAKE US A LEVEL 1 CHARACTER
	MOVEI	T1,^D100	;MAKE US FULL STRENGTH
	MOVEM	T1,U.POWR(U)	;DO IT
	MOVEM	T1,U.POWM(U)	;AND SET MAXIMUM
	AOS	H.PLRS		;ONE MORE PLAYER EXISTS
OLDPLR:	CALL	UNLOCK		;UNLOCK THE FILE
	ANDI	U,-1		;KEEP ONLY THE ADDRESS
	MOVEI	T1,-PLRADR(U)	;GET OFFSET INTO PLAYER AREA
	IDIVI	T1,PLRSIZ	;DIVIDE BY SIZE OF EACH DATA BLOCK
	MOVEM	T1,MYNUM	;REMEMBER FOR USE LATER
	MOVE	R,U.ROOM(U)	;GET THE ROOM NUMBER
	IMULI	R,ROMSIZ	;MULTIPLY BY SIZE OF EACH ROOM'S DATA
	ADDI	R,ROMADR	;OFFSET TO PROPER PLACE
CPOPJ:	RET			;DONE
	SUBTTL	SUBROUTINE TO FIND A PARTICULAR PLAYER




;CALLED TO SEARCH THE DATA FILE FOR A PARTICULAR PLAYER, AND RETURN
;THE ADDRESS OF HIS DATA BLOCK.
;CALL:
;  T1/	PLAYER NUMBER
;RETURNS:
;  +1:	NOT FOUND, FIRST FREE ADDRESS IN T2
;  +2:	FOUND, ADDRESS OF PLAYER'S DATA IN T2.
;USES NO OTHER ACS



FNDUSR:	HRLZ	T2,H.PLRS	;GET NUMBER OF PLAYERS READY
	MOVN	T2,T2		;MAKE INTO AOBJN POINTER
	ADDI	T2,PLRADR	;OFFSET TO THE FIRST PLAYER'S DATA
	CAIN	T2,PLRADR	;ANY PLAYERS?
	RET			;NO, NON-SKIP RETURN

FINDLP:	CAMN	T1,U.USER(T2)	;FOUND MY ENTRY YET?
	JRST	CPOPJ1		;YES, SKIP RETURN
	ADDI	T2,PLRSIZ-1	;NO, INCREMENT TO NEXT ENTRY
	AOBJN	T2,FINDLP	;AND KEEP SEARCHING
	RET			;FAIL
	SUBTTL	SUBROUTINE TO LOCK AND UNLOCK THE FILE




;SUBROUTINES TO INTERLOCK THE DATA FILE TO PREVENT TWO USERS FROM
;WRITING DATA AT THE SAME TIME.  THIS IS THE OLD "AOSE" INTERLOCK
;ALGORITHM.  TO HELP DETERMINE WHAT IS WRONG IF THE INTERLOCK IS
;WRECKED, WE SAVE DATA WHEN THE LOCK IS OBTAINED.  NO AC'S
;ARE CHANGED.



LOCK:	TXNN	F,FR.MAP	;MAKE SURE IT IS MAPPED IN
	FATAL	(Attempt to interlock file which is not mapped)	;FAIL
	TXNE	F,FR.LCK	;CALLING THIS WHILE LOCKED?
	FATAL	(Attempt to interlock file twice)	;YES
	ADJSP	P,4		;ALLOCATE SOME STACK
	DMOVEM	T1,-1(P)	;SAVE SOME AC'S
	DMOVEM	T3,-3(P)	;SO THEY AREN'T HURT
	MOVEI	T4,^D60		;TRY THIS FOR A MINUTE


LOCKLP:	GTAD			;READ THE TIME OF DAY
	MOVE	T2,MYJOB	;GET MY JOB NUMBER
	MOVE	T3,MYUSER	;AND WHO I AM
	AOSE	H.LOCK		;TRY TO GET THE LOCK
	JRST	NOLOCK		;FAILED, GO WAIT
	MOVEM	T1,H.LTIM	;SAVE THE TIME
	MOVEM	T2,H.LJOB	;AND THE JOB NUMBER
	MOVEM	T3,H.LUSR	;AND WHO I AM
	DMOVE	T3,-3(P)	;RESTORE THE ACS
	DMOVE	T1,-1(P)	;THAT WERE SAVED
	ADJSP	P,-4		;FIX STACK
	TXO	F,FR.LCK	;FILE IS LOCKED NOW
	RET			;DONE

NOLOCK:	MOVEI	T1,^D1000	;GET READY
	DISMS			;WAIT A BIT
	SOJG	T4,LOCKLP	;TRY AGAIN UNLESS TIMED OUT
	ERROR	(,,Can't get interlock on data file)	;COMPLAIN
;HERE TO UNLOCK THE FILE.  NO ACS ARE CHANGED.



UNLOCK:	TXNN	F,FR.LCK	;MAKE SURE FILE WAS LOCKED
	FATAL	(Attempt to unlock data file which wasn't locked)
	SETOM	H.LOCK		;MAKE THE INTERLOCK AVAILABLE
	PUSH	P,T1		;SAVE SOME ACS
	PUSH	P,T2		;THAT WE USE
	HRLZ	T1,FILJFN	;GET THE JFN READY
	MOVEI	T2,-1		;GET ALMOST LARGE ENOUGH COUNT
	UFPGS			;UPDATE THE FILE NOW
	  ERJMP	DIE		;FAILED
	POP	P,T2		;RESTORE THEM
	POP	P,T1		;AS THEY WERE
	TXZ	F,FR.LCK	;NOT LOCKED NOW
	RET			;DONE
	SUBTTL	SUBROUTINE TO OPEN DATA FILE AND MAP IT IN




;SUBROUTINE TO OPEN UP THE DATA FILE AND MAP IT IN.  NEVER SKIPS.
;DOESN'T RETURN IF ANY ERROR IS ENCOUNTERED.



FILOPN:	TXNE	F,FR.MAP	;IS FILE MAPPED IN YET?
	RET			;YES, DONE
	SETZB	U,R		;WE DON'T KNOW ROOM OR OUR LOCATION
	MOVX	T1,GJ%OLD+GJ%PHY+GJ%SHT	;FLAGS
	HRROI	T2,FILNAM	;FILE NAME
	GTJFN			;TRY TO GET A JFN
	  ERJMP	DIE		;FAILED
	MOVEM	T1,FILJFN	;SAVE THE JFN
	MOVX	T2,OF%RD+OF%WR+OF%THW+OF%DUD	;GET FLAGS
	OPENF			;TRY TO OPEN THE FILE
	  ERJMP	DIE		;FAILED
	HRLZ	T1,FILJFN	;GET READY
	MOVE	T2,[.FHSLF,,MAPADR/PAGSIZ]	;GET ARGS
	MOVX	T3,PM%RD+PM%WR+PM%CNT+<<MAPLST-MAPADR>/PAGSIZ>	;FLAGS
	PMAP			;MAP IN THE FILE
	  ERJMP	DIE		;FAILED
	TXO	F,FR.MAP	;FILE NOW MAPPED IN
	MOVE	T1,H.VERS	;GET THE VERSION OF THE FILE
	CAIN	T1,HDRVER	;IS THIS THE CORRECT VERSION?
	RET			;YES, ALL DONE
	CALL	FILCLS		;NO, CLOSE IT
	FATAL	(Wrong version in data file)	;DIE



;HERE IF AN ERROR IS ENCOUNTERED:


DIE:	HRROI	T1,[ASCIZ/
? /]				;GET READY
	PSOUT			;TYPE THE STRING
	MOVEI	T1,.PRIOU	;GET READY
	HRLOI	T2,.FHSLF	;TO TYPE MY ERROR
	SETZ	T3,		;ALL OF IT
	ERSTR			;PRINT ERROR
	  JFCL			;IGNORE FAILURE
	  JFCL
	HRROI	T1,[ASCIZ/
/]				;FINISHING TEXT
	PSOUT			;TYPE IT
	HALTF			;QUIT
	JRST	.-1		;STAY THAT WAY
	SUBTTL	SUBROUTINE TO CLOSE THE MAPPED FILE





;ROUTINE TO UNMAP THE FILE FROM CORE, AND CLOSE IT.  NEVER SKIPS.




FILCLS:	TXZN	F,FR.MAP	;IS FILE MAPPED IN?
	RET			;NO, NOTHING TO DO
	SETO	T1,		;WANT TO UNMAP FILE PAGES
	MOVE	T2,[.FHSLF,,<MAPADR/PAGSIZ>]	;FROM MY PROCESS
	MOVX	T3,PM%RD+PM%WR+PM%CNT+<<MAPLST-MAPADR>/PAGSIZ>	;FLAGS
	PMAP			;UNMAP THEM
	MOVE	T1,FILJFN	;GET THE JFN
	CLOSF			;RELEASE THE FILE
	  ERJMP	DIE		;FAILED
	SETZM	FILJFN		;CLEAR THE JFN
	RET			;DONE
	SUBTTL	SUBROUTINE TO INITIALIZE THE DATA FILE




;PRIVILEGED SUBROUTINE CALLED TO INITIALIZE THE DUNGEON.  THIS CONSISTS
;OF WRITING A NEW VERSION OF THE DATA FILE, WITH NO ROOMS AND NO PLAYERS.
;THE HEADER AREA IS SET UP TO A GOOD STATE.



FILINI:	MOVX	T1,GJ%FOU+GJ%SHT	;WANT A NEW VERSION
	HRROI	T2,FILNAM	;OF THE FILE
	GTJFN			;GET A JFN ON IT
	  ERJMP	DIE		;FAILED
	MOVEM	T1,FILJFN	;SAVE THE JFN
	MOVX	T2,OF%RD+OF%WR	;WANT TO WRITE THE FILE
	OPENF			;OPEN IT UP
	  ERJMP	DIE		;FAILED
	HRLI	T1,<.FBSIZ(CF%NUD)>	;EOF OFFSET AND NO UPDATE BIT
	SETO	T2,		;WHOLE WORD IS TO BE CHANGED
	HRLOI	T3,377777	;TO INFINITY
	CHFDB			;MAKE THE CHANGE
	  ERJMP	DIE		;FAILED
	HRLI	T1,<.FBBYV(CF%NUD)>	;WANT TO SET BYTE SIZE
	MOVX	T2,FB%BSZ	;MASK FOR IT
	MOVX	T3,<FLD(^D36,FB%BSZ)>	;VALUE
	CHFDB			;CHANGE IT
	  ERJMP	DIE		;FAILED
	HRLZ	T1,FILJFN	;MAP FROM PAGE ZERO
	MOVE	T2,[.FHSLF,,<MAPADR/PAGSIZ>]	;GET READY
	MOVX	T3,PM%RD+PM%WR+PM%CNT+<<MAPLST-MAPADR>/PAGSIZ>	;FLAGS
	PMAP			;MAP PAGE ZERO OF THE FILE
	  ERJMP	DIE		;FAILED
	MOVE	T1,[MAPADR,,MAPADR+1]	;GET READY
	SETZM	MAPADR		;TO CLEAR THE PAGE
	BLT	T1,MAPADR+HDRSIZ-1	;CLEAR THE HEADER
	MOVEI	T1,HDRVER	;GET THE VERSION OF THE DATA FILE
	MOVEM	T1,H.VERS	;INITIALIZE IT
	GTAD			;GET THE CURRENT TIME AND DATE
	MOVEM	T1,H.DATE	;REMEMBER IT
	MOVEI	T1,PLRADR-MAPADR	;GET OFFSET INTO FILE OF USER DATA
	MOVEM	T1,H.UADR	;REMEMBER IT
	MOVEI	T1,PLRSIZ	;GET SIZE OF EACH DATA AREA
	MOVEM	T1,H.USIZ	;REMEMBER IT
	MOVEI	T1,ROMADR-MAPADR	;GET OFFSET OF ROOM DATA
	MOVEM	T1,H.RADR	;REMEMBER IT
	MOVEI	T1,ROMSIZ	;GET SIZE OF EACH DATA AREA
	MOVEM	T1,H.RSIZ	;REMEMBER IT TOO
;MORE INITIALIZATION OF THE FILE:


	MOVE	T1,[MID,,MID]	;GET COORDINATES OF ROOM 0
	MOVEI	T2,0		;WHICH IS IN LEVEL 0
	CALL	MAKROM		;BUILD IT
	 FATAL	(Failed to build room 0)
	HRLOI	T1,DR.NEV	;GET CODE FOR NONEXISTANT DOORS
	MOVEM	T1,R.DIRS(S)	;PLACE IN FIRST DIRECTION
	MOVSI	T1,R.DIRS+0(S)	;GET ADDRESS
	IORI	T1,R.DIRS+1(S)	;AND NEXT ONE
	BLT	T1,R.DIRS+DIRMAX-1(S)	;MAKE ALL DIRECTIONS INVALID
	HRLOI	T1,DR.LVL	;NOW GET CODE FOR A LEVEL DOOR
	MOVEM	T1,R.DIRS(S)	;AND PLACE IN FIRST DIRECTION
	SETOM	H.LOCK		;MAKE THE INTERLOCK AVAILABLE
	TXO	F,FR.MAP	;ACT LIKE WE HAVE FILE MAPPED
	CALL	FILCLS		;CLOSE THE FILE
	RET			;THEN RETURN
	SUBTTL	SUBROUTINE TO MAKE A MAGIC PHRASE




;CALLED WITH A GENERATING NUMBER IN T1, TO USE THE NUMBER AND THE
;WORD TABLES TO STORE A MAGIC PHRASE INTO THE MAGTXT BUFFER.  CALL:
;
;  T1/	GENERATING NUMBER
;
;RETURNS:
;  +1:	ALWAYS, WITH TEXT STORED.
;
;THE MAGIC PHRASE IS FROM 2 TO 4 WORDS LONG, WHERE EACH WORD IS FROM
;2 TO 3 SYLLABLES IN LENGTH.



MAKWRD:	PUSH	P,RANNUM	;SAVE RANDOM NUMBER
	ADD	T1,H.DATE	;ADD IN TIME OF DUNGEON CREATION
	MOVEM	T1,RANNUM	;AND STORE THE GIVEN SEED
	CALL	RANDOM		;JUMBLE IT ONCE
	CALL	RANDOM		;DO AGAIN TO HELP IT
	MOVE	T4,[POINT 7,MAGTXT]	;GET POINTER TO BUFFER READY
	MOVEI	T1,3		;GET READY TO GET NUMBER OF WORDS
	CALL	RANDOM		;DO IT
	ADDI	T1,2		;ALWAYS HAVE AT LEAST 2 WORDS
	MOVEM	T1,TEMP		;REMEMBER NUMBER OF WORDS TO DO

MAKWLP:	MOVEI	T1,MAGSZ1	;GET NUMBER OF WORD PARTS IN TABLE
	CALL	RANDOM		;PICK ONE OUT
	MOVE	T1,MAGTB1(T1)	;GET THE WORD
	CALL	WRDSTF		;STORE IT IN THE BUFFER
	MOVEI	T1,MAGSZ2	;GET WORDS IN SECOND TABLE
	CALL	RANDOM		;PICK ONE OUT
	MOVE	T1,MAGTB2(T1)	;GET THE WORD
	CALL	WRDSTF		;STORE IT IN THE BUFFER
	MOVEI	T1,2		;GET SET
	CALL	RANDOM		;SEE IF WANT A THIRD SYLLABLE
	JUMPE	T1,WRDTWO	;NO, GO ON
	MOVEI	T1,MAGSZ3	;YES, GET NUMBER OF ENTRIES
	CALL	RANDOM		;PICK ONE
	MOVE	T1,MAGTB3(T1)	;GET THE WORD
	CALL	WRDSTF		;STORE THE WORD
WRDTWO:	MOVEI	T1," "		;GET A SPACE
	SOSG	TEMP		;COUNT DOWN WORDS TO GO
	SETZ	T1,		;LAST WORD, GET A NULL
	IDPB	T1,T4		;STORE A SPACE OR A NULL
	JUMPN	T1,MAKWLP	;CONTINUE IF NOT DONE
	POP	P,RANNUM	;OTHERWISE RESTORE RANDOM NUMBER
	RET			;AND RETURN
;SUBROUTINE TO STORE THE ASCII WORD IN T1 INTO THE TEXT POINTED
;TO BY T4.



WRDSTF:	JUMPE	T1,CPOPJ	;DONE WHEN GET A NULL
	SETZ	T2,		;CLEAR NEXT WORD
	ROTC	T1,7		;GET NEXT LETTER
	IDPB	T2,T4		;STORE IT
	JRST	WRDSTF		;AND LOOP
	SUBTTL	RANDOM NUMBER GENERATOR




;CALLED TO OBTAIN A RANDOM INTEGER IN A SPECIFIED RANGE FROM 0 TO N-1.
;CALL:
;	T1/	N
;RETURNS:
;	T1/	A NUMBER FROM 0 TO N-1 INCLUSIVE.
;
;CAN TRASH T2.




RANDOM:	PUSH	P,T1		;SAVE THE RANGE
	SKIPN	T1,RANNUM	;GET LAST RANDOM NUMBER
	TIME			;IF NONE, USE TIME AS A SEED
	IMUL	T1,[^D<125*125*125*125*125>]	;5**15 IS MAGIC
	ADDI	T1,^D17		;HELP ALONG IN CASE ZERO
	TXZ	T1,1B0		;MAKE SURE IT IS POSITIVE
	SKIPN	T1		;MAKE SURE NONZERO
	MOVEI	T1,^D17		;IF SO, FIX IT
	MOVEM	T1,RANNUM	;REMEMBER FOR NEXT CALL
	POP	P,T2		;RESTORE THE RANGE
	MUL	T1,T2		;PRODUCE THE RESULT
	RET			;DONE
	SUBTTL	SUBROUTINE TO TYPE OUT THE LATEST NEWS





;THIS ROUTINE IS CALLED TO LOOK UP AND TYPE THE LATEST INFORMATION
;ABOUT THE DUNGEON.  THE OUTPUT IS JUSTIFIED AS USUAL.  CALL:
;  T1/	JFN OF THE MESSAGE FILE
;RETURNS:
;  +1:	OUTPUT COMPLETED, JFN CLOSED.



DOMESS:	MOVEM	T1,MSGJFN	;SAVE THE JFN
	MOVX	T2,OF%RD+7B5	;WANT TO READ THE FILE
	OPENF			;TRY TO OPEN IT
	 ERJMP	MSGNO2		;FAILED
	DOCRLF			;START WITH A CRLF
	TXZ	F,FR.CRL	;MAKE CRLFS NOT MATTER AT FIRST

MSGLOP:	MOVE	T1,MSGJFN	;GET JFN
	BIN			;READ NEXT CHARACTER
	 ERJMP	MSGFIN		;ERROR, GO FINISH
	SKIPN	C,T2		;MOVE TO RIGHT AC
	JRST	MSGLOP		;BUT IGNORE NULLS
	CAIN	C,"&"		;SPECIAL CHARACTER?
	TXCA	F,FR.CRL	;YES, TOGGLE FLAG AND IGNORE IT
	PUTCHR			;NO, TYPE IT
	JRST	MSGLOP		;LOOP OVER ALL CHARACTERS


MSGFIN:	MOVE	T1,MSGJFN	;GET JFN READY
	RLJFN			;RELEASE IT
	 JFCL			;FAILED
	SETZM	MSGJFN		;CLEAR FROM CORE
	DOCRLF			;END IN A CRLF
	RET			;DONE


MSGNO2:	CALL	MSGFIN		;FINISH CLOSING FILE
MSGNO1:	STROUT	[ASCIZ/
Failed to read text file.
/]				;COMPLAIN
	RET			;AND RETURN
	SUBTTL	SUBROUTINE TO REBUILD THE COMMAND TABLE




;CALLED WHENEVER THE COMMAND TABLE IS NO LONGER VALID.  WE BUILD
;A TABLE OF COMMANDS USING TBADD FOR COMND TO USE.



BLDCMD:	MOVEI	T1,CMDLEN	;GET MAXIMUM NUMBER OF COMMANDS
	MOVEM	T1,CMDTAB	;AND INITIALIZE THE TABLE OF COMMANDS
	MOVSI	T3,-CMDLEN	;GET READY FOR LOOPING

BLDCML:	HRRZ	T1,CMDORG+1(T3)	;GRAB ADDRESS OF DATA WORD
	MOVE	T1,(T1)		;AND GRAB IT
	HLRZ	T2,CMDORG+1(T3)	;GET ADDRESS OF TEXT STRING
	MOVE	T2,(T2)		;THEN GET FIRST WORD OF STRING
	TXNN	T2,177B6	;IS THIS AN ABBREVIATION?
	MOVE	T1,(T1)		;YES, GET RIGHT DATA WORD
	HLRZ	T1,T1		;KEEP ONLY REASONS FOR REJECTING COMMAND
	TXNE	F,FR.PLY	;ARE WE PLAYING?
	TRZA	T1,C.PLY	;YES, ZAP THAT REASON
	TRZ	T1,C.NOP	;OTHERWISE ZAP NON-PLAYING REASON
	TXNE	F,FR.GOD	;ARE WE GODLY?
	TRZ	T1,C.GOD	;YES, ZAP THAT REASON
	TXNE	F,FR.DEB	;DEBUGGING?
	TRZ	T1,C.DEB	;YES, ZAP THAT REASON
	TRZ	T1,C.STS	;CLEAR THIS BIT ALWAYS
	JUMPN	T1,BLDNO	;DISALLOW COMMAND IF ANY REASONS LEFT
	MOVEI	T1,CMDTAB	;POINT TO COMMAND TABLE
	MOVE	T2,CMDORG+1(T3)	;GET ENTRY TO ADD
	TBADD			;INSERT IT
BLDNO:	AOBJN	T3,BLDCML	;LOOP OVER ALL COMMANDS
	TXZ	F,FR.BLD	;NO LONGER HAVE TO REBUILD THE TABLE
	RET			;DONE
	SUBTTL	COMMAND JSYS SUBROUTINES



;SUBROUTINES TO DO THE COMND JSYS.  THESE ROUTINES RETURN TO THE COMMAND
;SCANNER FOR A NEW COMMAND IF AN ERROR OCCURS, UNLESS THE CALL TO THEM
;WAS FOLLOWED BY AN ERJMP, IN WHICH CASE IT IS TAKEN.




;CALLED FROM NOISE MACRO TO PARSE A NOISE TEXT.


DONOIS:	HRROM	T2,NOIBLK+.CMDAT	;SAVE AS DATA
	MOVEI	T2,NOIBLK	;POINT TO BLOCK
	JRST	DOCMMD		;AND GO DO COMND JSYS




;CALLED FROM CONFRM MACRO TO CONFIRM A LINE.  AC T2 IS PRESERVED.


DOCNFM:	PUSH	P,T2		;SAVE THIS AC
	CMMD	[FLDDB. (.CMCFM)]	;DO THE CONFIRM
	POP	P,T2		;RESTORE AC
	RET			;DONE
;CALLED FROM CMMD MACRO TO DO THE ACTUAL WORK.


DOCMMD:	COMND			;PARSE THE FUNCTION
	  ERJMP	BADCMD		;ERROR, GO COMPLAIN
	TXNN	T1,CM%NOP	;PARSED CORRECTLY?
	RET			;YES, DONE



BADCMD:	TXNN	F,FR.PLY	;ACTUALLY PLAYING THE GAME?
	JRST	BADCMT		;NO, COMPLAIN NORMALLY
	MOVEI	T1,.FHSLF	;GET READY
	GETER			;READ LAST ERROR
	HRRZ	T1,T2		;GET CODE BY ITSELF
	CAIN	T1,NPXNOM	;UNKNOWN COMMAND?
	JRST	UNKCMD		;YES
BADCMT:	HRROI	T1,[ASCIZ/
? /]				;GET STARTING TEXT
	PSOUT			;TYPE IT
	MOVEI	T1,.PRIOU	;GET READY
	HRLOI	T2,.FHSLF	;TO OUTPUT ERROR
	SETZ	T3,		;ALL OF IT
	ERSTR
	JFCL
	JFCL
	HRROI	T1,[ASCIZ/

/]				;MORE TEXT
	PSOUT			;TYPE IT
	MOVE	P,SAVEP		;RESTORE STACK
	JRST	GETCMD		;DO REPARSE



UNKCMD:	HRROI	T1,[ASCIZ/
I don't know how to do that.

/]				;GET TEXT
	PSOUT			;COMPLAIN
	MOVE	P,SAVEP		;RESTORE STACK
	JRST	GETCMD		;AND REPARSE
	SUBTTL	SUBROUTINE TO TYPE THE ELEMENTS IN A LIST




;CALLED TO HANDLE THE PUNCTUATION AND CONCATINATION OF THE ELEMENTS
;WHICH MAKE UP A LIST.  THE LIST OF ELEMENTS ASSUMES ONE OF THE
;FOLLOWING FORMS, DEPENDING ON THE NUMBER OF ELEMENTS:
;
;	ELEMENT1
;	ELEMENT1 and ELEMENT2
;	ELEMENT1, ELEMEN2, and ELEMENT3
;	...
;
;ARGUMENTS:
;     T1/  DATA,,ADDRESS	;ADDRESS IS A SUBROUTINE TO TYPE OUT
;				;THE CURRENT ELEMENT, AND THE DATA WILL
;				;BE PUT IN T1 FOR THE SUBROUTINE'S USE
;
;OR:  T1/  0			;NO MORE ELEMENTS IN LIST
;
;BEFORE THE FIRST CALL, CLEAR LOCATION LISOLD.
;WHEN DONE WITH THE LIST, LOCATION LISCNT WILL CONTAIN THE
;TOTAL NUMBER OF ELEMENTS THAT WERE TYPED.  USES ONLY T1 AND T2.



DOLISE:	SETZ	T1,		;INDICATE END OF LIST
DOLIST:	SKIPN	T2,LISOLD	;GET PREVIOUS ELEMENT
	SETZM	LISCNT		;NONE, SO CLEAR NUMBER OF ELEMENTS
	MOVEM	T1,LISOLD	;REMEMBER CURRENT ELEMENT FOR NEXT CALL
	SKIPN	T1,LISCNT	;GET ELEMENTS TYPED
	JRST	DOLINC		;JUMP IF NONE YET
	CAIN	T1,1		;JUST ONE?
	SKIPA	T1,[[ASCIZ/ and /]]	;GET SOME TEXT
	MOVEI	T1,[ASCIZ/, and /]	;OR OTHER TEXT
	SKIPE	LISOLD		;MORE COMING?
	MOVEI	T1,[ASCIZ/, /]	;YES, GET THIS TEXT INSTEAD
	CALL	TTYSTR		;TYPE STRING
DOLINC:	JUMPE	T2,CPOPJ	;DONE IF NO ELEMENT TO LIST
	HLRZ	T1,T2		;GET THE DATA READY
	CALL	(T2)		;CALL ROUTINE TO TYPE THE ELEMENT
	AOS	LISCNT		;COUNT NUMBER OF ELEMENTS TYPED
	RET			;DONE
	SUBTTL	ROUTINE TO FORMAT TERMINAL OUTPUT




;THIS SUBROUTINE BUFFERS OUTPUT FOR THE TERMINAL, AND INSERTS
;CRLFS AT APPROPRIATE PLACES SO THAT THE OUTPUT IS JUSTIFIED
;REASONABLY.  EXTRA SPACES AT THE END OF A LINE ARE DISCARDED.
;USE OF ROUTINES:
;
;	CALL	TTYINI		;INITIALIZE BUFFERS AND POINTERS
;
;LOOP:	MOVEI	C,CHAR		;GET CHARACTER
;	CALL	TTYOUT		;GIVE TO FORMATTING SUBROUTINE
;	...			;CONTINUE
;
;	CALL	TTYPNT		;FORCE OUT REMAINING OUTPUT
;
;DESTROYS AC C.





;HERE TO FORCE OUT ANY REMAINING OUTPUT:


TTYPNT:	MOVE	T1,ENDLTR	;GET WHERE LAST LETTER WAS
	CAMN	T1,[POINT 7,BUFF]	;ANYTHING TO FORCE OUT?
	RET			;NO
	SETZ	T1,		;GET A NULL
	IDPB	T1,ENDLTR	;MAKE THE STRING ASCIZ
	HRROI	T1,BUFF		;POINT TO BUFFER
	PSOUT			;TYPE IT
				;FALL INTO INITIALIZATION CODE



;HERE TO INITIALIZE THE BUFFER:


TTYINI:	MOVE	C,[POINT 7,BUFF];GET POINTER TO START OF BUFFER
	MOVEM	C,BUFPTR	;SET UP CURRENT POINTER
	MOVEM	C,ENDLTR	;AND WHERE "LAST LETTER" WAS
	SETZM	BEGWRD		;NO WORD HAS STARTED YET
	SETZM	@FULADR		;BUFFER IS NOT FULL YET
	SETZM	BUFOVR		;AND HAS NOT OVERFLOWED
	RET			;DONE
TTYOUT:	CAIN	C,15		;CARRIAGE RETURN?
	RET			;YES, IGNORE IT
	CAIN	C,12		;LINE FEED?
	JRST	TTYLIN		;YES, GO SEE WHAT TO DO
	CAIN	C," "		;A SPACE?
	JRST	TTYSPC		;YES, DIFFERENT HANDLING
	CAIN	C,"	"	;A TAB?
	JRST	TTYTAB		;YES, GO HANDLE IT
	IDPB	C,BUFPTR	;STORE THE CHARACTER
	MOVE	C,BUFPTR	;GET CURRENT POINTER
	MOVEM	C,ENDLTR	;AND SAVE AS LAST LETTER SEEN
	SKIPN	BEGWRD		;STARTING A NEW WORD?
	MOVEM	C,BEGWRD	;YES, REMEMBER WHERE IT STARTS
	SKIPN	@FULADR		;BUFFER FILLED UP?
	RET			;NO, DONE
	PUSH	P,T1		;YES, SAVE AN AC WE NEED
	SETZ	T1,		;GET A NULL
	IDPB	T1,ENDWRD	;TERMINATE STRING ENDING WITH LAST FULL WORD
	HRROI	T1,BUFF		;POINT TO BUFFER
	CALL	SAVOUT		;TYPE LINE UP TO LAST COMPLETE WORD
	HRROI	T1,[ASCIZ/
/]				;GET A CRLF
	CALL	SAVOUT		;TYPE IT
	MOVE	T1,[POINT 7,BUFF]	;GET INITIAL POINTER
	MOVEM	T1,BUFPTR	;AND RESET CURRENT LOCATION
	SETO	T1,		;WANT TO BACKUP A CHARACTER
	ADJBP	T1,BEGWRD	;POINT JUST BEFORE CURRENT WORD
BUFBLT:	ILDB	C,T1		;GET ANOTHER LETTER OF CURRENT WORD
	IDPB	C,BUFPTR	;AND MOVE TO FRONT OF BUFFER
	CAME	T1,ENDLTR	;MOVED THE LAST LETTER SEEN?
	JRST	BUFBLT		;NOT YET, KEEP GOING
	MOVE	T1,BUFPTR	;GET CURRENT POINTER
	MOVEM	T1,ENDLTR	;AND SET WHERE LAST LETTER IS
	MOVE	T1,[POINT 7,BUFF,6]	;GET POINTER TO FIRST LETTER
	MOVEM	T1,BEGWRD	;AND REMEMBER WHERE WORD STARTS
	SETZM	@FULADR		;CLEAR THE BUFFER FULL INDICATOR
	SETZM	BUFOVR		;AND THE OVERFLOW WORD
	POP	P,T1		;RESTORE THE AC
	RET			;AND RETURN
;HERE WHEN RECEIVE A TAB:



TTYTAB:	PUSH	P,T1		;SAVE SOME AC'S
	PUSH	P,T2		;THAT WE'LL USE
	LDB	T1,[POINT 6,BUFPTR,5]	;GET POSITION OF LAST BYTE
	IDIVI	T1,7		;OBTAIN WHICH BYTE IT IS
	MOVEI	T2,5		;GET CHARS IN A WORD
	SUB	T2,T1		;GET NUMBER OF CHARS IN THIS WORD
	HRRZ	T1,BUFPTR	;GET WORD WE'RE CURRENTLY ON
	SUBI	T1,BUFF		;SUBTRACT START OF BUFFER
	IMULI	T1,5		;FIVE CHARACTERS TO A WORD
	ADD	T1,T2		;ADD IN PARTIAL WORD
TABLOP:	CALL	TTYSPC		;OUTPUT A SPACE
	ADDI	T1,1		;ADVANCE COLUMN
	TRNE	T1,7		;REACHED A TAB STOP YET?
	JRST	TABLOP		;NO, KEEP GOING
	POP	P,T2		;YES, RESTORE AC'S
	POP	P,T1		;THAT WE USED
	RET			;AND DONE




;HERE WHEN RECEIVE A SPACE:


TTYSPC:	SKIPE	BUFOVR		;STARTING TO OVERFLOW THE BUFFER?
	RET			;YES, IGNORE MORE SPACES
	MOVEI	C," "		;GET A SPACE
	IDPB	C,BUFPTR	;STORE IT
	MOVE	C,ENDLTR	;GET WHERE LAST LETTER WAS
	MOVEM	C,ENDWRD	;THEN SET WHERE LAST WORD ENDED
	SETZM	BEGWRD		;NO NEW WORD YET BEGUN
	RET			;DONE






;HERE TO FORCE OUT NEW LINES WHEN NECESSARY:




TTYLIN:	TXNN	F,FR.CRL	;WANT CRLFS PRESERVED?
	JRST	TTYSPC		;NO, MAKE IT A SPACE INSTEAD
TTYCRL:	PUSH	P,T1		;SAVE AN AC
	CALL	TTYPNT		;FORCE OUTPUT OUT
	HRROI	T1,[ASCIZ/
/]				;GET A FINAL CRLF
	CALL	SAVOUT		;TYPE IT
	POP	P,T1		;RESTORE THE AC
	RET			;AND RETURN
	SUBTTL	OUTPUT STORAGE ROUTINES




;THESE ROUTINES ARE USED TO STORE OUTPUT FOR LATER TYPING.  THIS IS
;NECESSARY WHEN OUTPUT IS GENERATED WHILE THE FILE IS LOCKED.  WE
;CANNOT ACTUALLY TYPE STUFF WITH THE FILE LOCKED, BECAUSE WE MIGHT
;GO INTO AN OUTPUT WAIT.  SO THE OUTPUT IS INTERCEPTED AND STORED,
;AND LATER WHEN THE FILE IS UNLOCKED, IT CAN BE OUTPUT.






;HERE TO INITIALIZE THINGS SO OUTPUT IS STORED:


SAVINI:	SKIPE	OUTPTR		;ALREADY SAVING OUTPUT?
	RET			;YES, DO NOTHING
	SETZM	OUTBUF		;CLEAR FIRST WORD
	SETZM	OUTOVR		;AND OVERFLOW WORD
	MOVE	T1,[POINT 7,OUTBUF]	;GET BYTE POINTER
	MOVEM	T1,OUTPTR	;AND SET UP STORAGE POINTER
	RET			;DONE




;HERE TO FINALLY TYPE FOR REAL THE STORED OUTPUT:


SAVPNT:	CALL	TTYPNT		;FORCE OUT STUFF WAITING TO GO
	SKIPN	OUTPTR		;ANY STORAGE POINTER?
	RET			;NO, NOTHING TO PUNT
	SETZ	T1,		;YES, GET A NULL
	IDPB	T1,OUTPTR	;MAKE STRING ASCIZ
	SETZM	OUTPTR		;THEN CLEAR STORAGE POINTER
	HRROI	T1,OUTBUF	;POINT TO BUFFER
	SKIPE	OUTBUF		;ANYTHING ACTUALLY THERE?
	PSOUT			;YES, TYPE IT
	HRROI	T1,[ASCIZ/
% Storage buffer overflowed, increase size to prevent lossage.
/]				;GET STRING
	SKIPE	OUTOVR		;DID WE OVERFLOW?
	PSOUT			;YES, SAY WHAT HAPPENED
	RET			;DONE
;HERE TO GIVE OUTPUT TO EITHER THE SCREEN, OR TO STORAGE FOR LATER
;OUTPUT.  POINTER TO STRING IS IN T1.



SAVOUT:	SKIPE	OUTPTR		;ANY STORAGE OF OUTPUT WANTED?
	JRST	SAVYES		;YES, GO DO IT
	TXNE	F,FR.LCK	;TRYING TO OUTPUT WHILE FILE LOCKED?
	 FATAL	(,,Attempting to output while data file is locked.)
	PSOUT			;NO, TYPE STRAIGHT
	RET			;AND RETURN


SAVYES:	TLC	T1,-1		;SEE IF LEFT HALF IS -1
	TLCN	T1,-1		;IS IT?
	HRLI	T1,(POINT 7,)	;YES, MAKE REASONABLE POINTER
	MOVEM	T1,OUTTMP	;SAVE FOR USE

SAVLOP:	SKIPE	OUTOVR		;OVERFLOWING?
	RET			;YES, STOP
	ILDB	T1,OUTTMP	;GET NEXT CHARACTER
	JUMPE	T1,CPOPJ	;DONE ON A NULL
	IDPB	T1,OUTPTR	;STORE CHAR
	JRST	SAVLOP		;LOOP
	SUBTTL	LUUO HANDLER



;ROUTINE TO PROCESS LUUOS.  LUUOS ARE USED AS A CONVENIENT WAY
;TO OUTPUT TEXT AND NUMBERS IN ONE INSTRUCTION.  ALL THESE LUUOS
;CAN TRASH AC'S T1-T3.



LUUO:	MOVE	T1,@.JBUUO	;GET THE ARGUMENT FOR THE UUO
	MOVEM	T1,UUOARG	;SAVE IT IN A SAFE PLACE
	LDB	T1,[POINT 9,.JBUUO,8]	;GET THE OPCODE
	CAILE	T1,MAXUUO	;SEE IF IT IS LEGAL
BADUUO:	FATAL	(Illegal LUUO executed)
	JRST	@LUUTAB(T1)	;YES, GO TO IT




;TABLE OF THE LUUOS WE HANDLE:


LUUTAB:	EXP	BADUUO		;(0) ILLEGAL
	EXP	STRUUO		;(1) TYPE AN ASCIZ STRING
	EXP	DECUUO		;(2) OUTPUT A DECIMAL NUMBER
	EXP	OCTUUO		;(3) OUTPUT AN OCTAL NUMBER
	EXP	DATUUO		;(4) OUTPUT A DATE
	EXP	CHRUUO		;(5) OUTPUT A SINGLE CHARACTER

	MAXUUO==.-LUUTAB-1	;HIGHEST KNOWN LUUO
;ROUTINES TO HANDLE THE VARIOUS TYPES OF OUTPUT:




;HERE TO TYPE A STRING.  THE USUAL CASE IS THAT CRLFS IN THE STRING
;ARE PRESERVED.  THE SPECIAL CHARACTER "&" WILL TOGGLE THAT CONDITION,
;SO THAT A CRLF IS TREATED AS A SPACE, TO MAKE MULTI-LINE JUSTIFIED
;OUTPUT EASIER.


STRUUO:	MOVE	T1,.JBUUO	;GET THE ADDRESS OF THE STRING
TTYSTR:	HRLI	T1,(POINT 7,)	;CREATE A BYTE POINTER
	TXO	F,FR.CRL	;START OFF BELIEVING CRLFS
TTYSTL:	ILDB	C,T1		;GET THE NEXT CHARACTER
	JUMPE	C,CPOPJ		;DONE WITH A NULL
	CAIN	C,"&"		;SPECIAL CHARACTER?
	TXCA	F,FR.CRL	;YES, COMPLEMENT FLAG AND FORGET IT
	PUTCHR			;NO, OUTPUT IT
	JRST	TTYSTL		;LOOP UNTIL DONE



USROUT:	MOVE	T2,T1		;MOVE TO BETTER AC
	HRROI	T1,TMPBUF	;POINT TO BUFFER
	DIRST			;STORE IT
	 ERJMP [CHROUT "#"	;FAILED, TYPE HASH MARK TO INDICATE A NUMBER
		HRRZ T1,T2	;GET NUMBER
		JRST TTYOCT]	;TYPE IT AND RETURN
	STROUT	TMPBUF		;OUTPUT NAME
	RET			;AND RETURN




OCTUUO:	SKIPA	T1,UUOARG	;GET THE NUMBER TO TYPE
DECUUO:	SKIPA	T1,UUOARG	;GET THE NUMBER TO TYPE
TTYOCT:	SKIPA	T3,[^D8]	;SET FOR OCTAL
TTYDEC:	MOVEI	T3,^D10		;SET FOR DECIMAL
	JUMPGE	T1,TTYNUM	;GO IF NONNEGATIVE
	MOVEI	C,"-"		;GET MINUS SIGN
	PUTCHR			;OUTPUT IT
	MOVM	T1,T1		;GET ABSOLUTE MAGNITUDE
TTYNUM:	IDIVI	T1,(T3)		;GET NEXT DIGIT
	JUMPE	T1,TTYNUF	;DONE WHEN HAVE A NULL
	HRLM	T2,(P)		;SAVE DIGIT
	CALL	TTYNUM		;LOOP
	HLRZ	T2,(P)		;GET BACK DIGIT
TTYNUF:	MOVEI	C,"0"(T2)	;MAKE ASCII
	PUTCHR			;OUTPUT IT
	RET			;AND DONE



DECSP7:	MOVEI	C," "		;GET SPACE
	CAMGE	T1,[^D1000000]	;LESS THEN SEVEN DIGITS?
	PUTCHR			;YES
DECSP6:	MOVEI	C," "		;GET SPACE READY
	CAIGE	T1,^D100000	;LESS THAN SIX DIGITS?
	PUTCHR			;YES
DECSP5:	MOVEI	C," "		;GET A SPACE
	CAIGE	T1,^D10000	;LESS THAN FIVE DIGITS?
	PUTCHR			;OUTPUT IT
DECSP4:	MOVEI	C," "		;GET SPACE
	CAIGE	T1,^D1000	;LESS THAN FOUR DIGITS?
	PUTCHR			;OUTPUT IT
DECSP3:	MOVEI	C," "		;GET SPACE
	CAIGE	T1,^D100	;LESS THAN THREE DIGITS?
	PUTCHR			;YES, OUTPUT IT
DECSP2:	MOVEI	C," "		;GET SPACE
	CAIGE	T1,^D10		;LESS THAN TWO DIGITS?
	PUTCHR			;TYPE IT
	JRST	TTYDEC		;THEN OUTPUT THE NUMBER
TTYSIX:	JUMPE	T1,CPOPJ	;DONE WITH A NULL
	SETZ	T2,		;CLEAR NEXT AC
	ROTC	T1,6		;SHIFT IN NEXT CHAR
	MOVEI	C," "(T2)	;MAKE ASCII
	PUTCHR			;TYPE IT
	JRST	TTYSIX		;LOOP




;ROUTINES TO OUTPUT A NUMBER IN THE FORM  NNN.NNNN, NN.NNNN, OR N.NNNN,
;WHERE THE DIVISOR IS IN T1, AND THE DIVIDEND IS IN T2.


TTYFI3:	SKIPA	T3,[EXP DECSP3]	;GET ROUTINE TO USE
TTYFI2:	MOVEI	T3,DECSP2	;OR OTHER ROUTINE
	SKIPA			;PROCEED
TTYFI1:	MOVEI	T3,TTYDEC	;STANDARD OUTPUT
	PUSH	P,T2		;SAVE DIVIDEND
	IDIV	T1,T2		;GET INTEGER PART FIRST
	PUSH	P,T2		;SAVE REMAINDER
	CALL	(T3)		;OUTPUT INTEGER PART
	CHROUT	"."		;THEN A DOT
	POP	P,T2		;RESTORE REMAINDER
	MOVEI	T3,4		;GET NUMBER OF DIGITS TO PRINT

TTYFXL:	MOVE	T1,T2		;COPY REMAINDER
	IMULI	T1,^D10		;SCALE UP
	IDIV	T1,0(P)		;GET NEXT DIGIT
	CHROUT	"0"(T1)		;OUTPUT IT
	SOJG	T3,TTYFXL	;LOOP
	POP	P,T1		;FIX STACK
	RET			;DONE
;ROUTINE TO OUTPUT SINGULAR OR PLURAL TEXTS. CALL:
;	T1/	NUMBER TO DETERMINE SINGULARNESS FROM
;	T2/	[ASCIZ/PLURAL TEXT/],,[ASCIZ/SINGULAR TEXT/]
;  OR:	T2/	0,,[ASCIZ/SINGULAR TEXT/] IF PLURAL IS SINGULAR + "S"
;CALL PLURNM TO OUTPUT NUMBER AND TEXT, OR PLURTX TO OUTPUT JUST THE
;TEXT.  USES T1-T3



PLURNM:	DMOVEM	T1,PLURTM	;SAVE ARGUMENTS FOR AWHILE
	SKIPN	T1		;ZERO SPECIFIED?
	STROUT	[ASCIZ/no/]	;YES, SAY THIS
	SKIPE	T1,PLURTM	;GET BACK NUMBER AND SEE IF NONZERO
	CALL	TTYDEC		;YES, OUTPUT IT
	CHROUT	" "		;THEN A SPACE
	DMOVE	T1,PLURTM	;RESTORE NUMBER AND TEXT

PLURTX:	SOJN	T1,PLURYS	;JUMP ON IF WANT PLURAL CASE
	HRRZ	T1,T2		;SINGULAR, GET ADDRESS
	JRST	TTYSTR		;GO OUTPUT IT

PLURYS:	HLRZ	T1,T2		;GET PLURAL STRING IF ANY
	JUMPN	T1,TTYSTR	;IF ONE, OUTPUT IT
	HRRZ	T1,T2		;OTHERWISE GET SINGULAR TEXT
	CALL	TTYSTR		;OUTPUT IT
	CHROUT	"s"		;THEN MAKE IT PLURAL IN STANDARD WAY
	RET			;DONE



GOLOUT:	MOVEI	T2,[ASCIZ/gold piece/]	;POINT TO TEXT
	JRST	PLURNM		;GO TO OTHER CODE



MONOUT:	HRLI	T1,(POINT 7,)	;FINISH BYTE POINTER
MONOUL:	ILDB	C,T1		;GET NEXT CHARACTER
	CAIN	C," "		;SPACE?
	JRST	TTYSTL		;YES, GO START TYPING NOW
	JUMPN	C,MONOUL	;NO, KEEP EATING
	RET			;STRING ENDED
DATUUO:	HRROI	T1,TMPBUF	;POINT TO BUFFER
	MOVE	T2,UUOARG	;GET THE DATE TO TYPE
	MOVX	T3,OT%NTM	;DON'T WANT THE TIME OUTPUT
	ODTIM			;STORE STRING
	MOVEI	T1,TMPBUF	;POINT TO BUFFER
	JRST	TTYSTR		;AND OUTPUT IT



CHRUUO:	HRRZ	C,.JBUUO	;GET THE CHARACTER
	PUTCHR			;OUTPUT IT
	RET			;DONE
	SUBTTL	ERROR ROUTINES




;HERE FROM THE ERROR MACRO.  THE ARGUMENTS TO THIS MACRO ARE:
;	ERROR	(INST1,INST2,TEXT)
;WHERE:
;
;INST1	IS AN INSTRUCTION EXECUTED BEFORE THE DATA FILE IS UNLOCKED.
;	USUALLY THIS WILL PUT SOME DATA IN T3 OR T4 FOR USE LATER.
;INST2	IS AN INSTRUCTION EXECUTED AFTER THE FILE IS UNLOCKED AND
;	THE BEGINNING TEXT HAS BEEN TYPED.
;TEXT	IS THE TEXT TO TYPE AFTER THE FILE IS UNLOCKED, BUT BEFORE
;	INST2 IS EXECUTED.
;
;ANY NULL ARGUMENT IS HANDLED PROPERLY.  ON ENTRY TO THIS ROUTINE,
;ERRTXT HAS THE POINTER TO THE TEXT IF ANY, T1 HAS INST1 IF ANY,
;AND T2 HAS INST2 IF ANY.



DOERR:	TXO	F,FR.CRL	;CRLFS MATTER NOW
	MOVEM	T2,ERRXCT	;REMEMBER INSTRUCTION FOR LATER
	SKIPE	T1		;ANY PRELIMINARY INSTRUCTION?
	XCT	T1		;YES, DO IT
	TXNE	F,FR.LCK	;IS THE DATA FILE LOCKED?
	CALL	UNLOCK		;YES, FREE IT
	SKIPE	T1,ERRTXT	;ANY TEXT TO TYPE OUT?
	CALL	TTYSTR		;YES, TYPE IT
	SKIPE	T1,ERRXCT	;ANY TRAILING INSTRUCTION TO DO?
	XCT	T1		;YES, DO IT
	DOCRLF			;FINISH WITH EXTRA CRLF
DOERRF:	CALL	SAVPNT		;FORCE OUT ALL OUTPUT
	MOVE	P,SAVEP		;RESTORE COMMAND LEVEL STACK
	JRST	GETCMD		;AND GET A NEW COMMAND




;HERE FOR A FATAL ERROR.  THESE ARE NOT SUPPOSED TO HAPPEN.
;WE JUST QUIT QUICKLY AND STAY THERE.  T4 HAS POINTER TO
;STRING TO BE TYPED.



DOFATL:	TXNE	F,FR.LCK	;WAS THE FILE LOCKED UP?
	CALL	UNLOCK		;YES, UNLOCK IT FIRST
	MOVE	T1,T4		;GET POINTER TO STRING
	PSOUT			;TYPE THE ERROR
	HALTF			;QUIT
	JRST	.-1		;STAY THAT WAY
	SUBTTL	DATA FOR COMND JSYS


CMDBLK:	EXP	NEWPAR		;FLAGS,,REPARSE ADDRESS
	XWD	.PRIIN,.PRIOU	;INPUT,,OUTPUT JFNS
	EXP	0		;CONTROL-R POINTER, FILLED IN AT RUNTIME
	XWD	-1,TXTBUF	;POINTER TO TEXT BUFFER
	XWD	-1,TXTBUF	;POINTER TO CURRENT POSITION
	EXP	TXTLEN		;NUMBER OF CHARS IN BUFFER
	EXP	0		;COUNT
	XWD	-1,ATMBUF	;POINTER TO ATOM BUFFER
	EXP	TXTLEN		;NUMBER OF CHARACTERS IN BUFFER
	EXP	JFNBLK		;POINTER TO GTJFN BLOCK


JFNBLK:	EXP	GJ%OLD		;FLAGS,,GENERATION NUMBER
	XWD	.PRIIN,.PRIOU	;INPUT,,OUTPUT JFNS
	BLOCK	20		;NO DEFAULTS



NOIBLK:	FLDDB.	(.CMNOI)	;BLOCK FOR NOISE FUNCTION
	SUBTTL	TABLES ABOUT THE MONSTERS




;HERE TO EXPAND THE MONS MACRO DEFINED EARLIER INTO THE VARIOUS
;TABLES NEEDED FOR THE PROGRAM.



	XALL			;ALLOW EXPANSIONS HERE


	DEFINE	XX(TF,HIT,MEAN,NAME),<
	<TF>B0+[ASCIZ/NAME/]	;;GENERATE FLAGS AND TEXT
>


MONTXT:	MONS			;EXPAND THE MACRO


	MONNUM==.-MONTXT	;NUMBER OF MONSTERS
	DEFINE	XX(TF,HIT,MEAN,NAME),<
	XWD	^D<HIT>,^D<MEAN>	;DEFENDING/ATTACKING DATA FOR NAME
>


MONPWR:	MONS			;EXPAND THE MACRO


	SALL			;RETURN TO NORMAL LISTING
	SUBTTL	ATTACK AND STRENGTH TEXTS




;THE FOLLOWING TABLES ARE USED TO OUTPUT THE RESULTS OF A BATTLE,
;AND ALSO HOW STRONG A MONSTER OR WE ARE.  EACH TABLE IS IN THE
;SAME FORMAT, WHERE THE RIGHT HALF POINTS TO THE STRING TO OUTPUT,
;AND THE LEFT HALF IS THE AMOUNT OF STRENGTH OR DAMAGE REQUIRED
;FOR THAT OUTPUT TO APPLY.  THE TABLES ARE ORDERED.



	DEFINE	STR(NUM,TEXT),<
	XWD	^D<NUM>,[ASCIZ/TEXT  /]
>


STRMON:	STR	0,on it's last legs!!
	STR	2,very very weak!!
	STR	4,rather weak now.
	STR	8,reasonably strong.
	STR	16,powerful.
	STR	25,amazingly powerful!!
	STR	50,infinitely powerful!!

	STRMNU==.-STRMON	;NUMBER OF ENTRIES



STRUS:	STR	0,about ready to die!!!!
	STR	5,extremely weak!!!
	STR	10,very weak!
	STR	20,pretty weak.
	STR	30,less than half your normal strength.
	STR	50,about half your normal strength.
	STR	70,reasonably strong.
	STR	80,very strong.
	STR	90,almost at full strength.
	STR	100,perfect!!

	STRUNU==.-STRUS		;NUMBER OF ENTRIES



STRWIN:	STR	0,You missed completely.
	STR	1,The monster was barely nicked.
	STR	2,You wounded the monster slightly.
	STR	3,The monster was gashed by that blow.
	STR	4,That blow slashed the monster greatly!
	STR	5,What a teriffic blow!!  Blood is pouring out of the wound!!

	STRWNU==.-STRWIN	;NUMBER OF ENTRIES




STRLOS:	STR	0,The monster missed you.
	STR	1,The monster just nicked you.
	STR	2,You were wounded by the monster.
	STR	3,The monster wounded you a lot.
	STR	4,You got damaged a lot in that attack!
	STR	5,The monster gashed you terribly!!

	STRLNU==.-STRLOS	;NUMBER OF TEXTS
	SUBTTL	TABLE OF MAGIC ITEMS





;THE FOLLOWING TABLE GIVES THE TEXT FOR THE MAGIC ITEMS.  THIS
;IS DONE BY EXPANDING THE ITEMS MACRO DEFINED EARLIER.



	DEFINE	XX(CODE,KEYWORD,TEXT),<
	IFDIF	<CODE><NOTITEM>,<
	XWD	[ASCIZ/KEYWORD/],[ASCIZ/TEXT/]
>
>


ITMTAB:	ITEMS			;BUILD THE TABLE


	ITMNUM==.-ITMTAB	;NUMBER OF ITEMS IN TABLE
	SUBTTL	TABLE OF MAGIC PHRASES




;THE FOLLOWING THREE TABLES ARE USED TO GENERATE MAGIC WORDS.
;A MAGIC PHRASE IS FROM 1 TO 3 WORDS, WHERE EACH WORD IS FROM
;2 TO 3 SYLLABLES FROM THE FOLLOWING TABLES.  THE PARTICULAR
;PHRASE GENERATED IS BASED ON A RANDOM NUMBER.




	DEFINE	SS(CHARS),<
	IRP	<CHARS>,<
	ASCII	/CHARS/
>
>


MAGTB1:	SS	<AB,AC,AL,AN,AS,BIN,BOR,CHO,CON,DAN,DIP,DRU,ED,EX,FOR,FREC>
	SS	<GRA,HER,IN,JOL,LIC,MAG,MOC,MOR,NIT,OM,ORA,PAR,PEN,PLAN>
	SS	<POR,REB,RET,SCOR,SEAR,SID,SPAR,SUB,TEN,THAN,TOG,TRAD,TUM>
	SS	<TYP,UND,VEC,VIOL,WAT,WON,YAW,ZERF>

	MAGSZ1==.-MAGTB1	;NUMBER OF WORDS


MAGTB2:	SS	<FEND,COB,WARE,DERM,WORT,TUBE,GAG,DATE,TINE,TOOT,PRES>
	SS	<TROS,VA,TENT,STER,GAL,NAT,CHIN,MAS,YON,ZUR,POD,DERN>
	SS	<DEL,PIAL,PHAR,LON,SER,TUS,STED,DON,FLAN,PEEN,PLEX>
	SS	<PHYT,FEL,LUD,VINC,VEAL,BRIC,PUL,FID,TORY,TION,THAT>
	SS	<KISH,LIZA,VER,WHAM,LES,ROR,EPID,NYS>

	MAGSZ2==.-MAGTB2	;NUMBER OF WORDS


MAGTB3:	SS	<BAT,LY,AGE,INE,PY,PHIC,OIL,THER,IUM,IAL,THOS,FY,ADE>
	SS	<NUE,EL,GLE,PER,EAT,LER,ANG,ENCE,ITY,INE,ASE,RUM>
	SS	<TIVE,SATE,MAND,LA,OOT,CON,NOMY,TICS,ACH,IZE,BLE,ILE>
	SS	<THER,ORB,KER,TOR,OUS,ISM,DEX,OOD,EAL,NAM,IZE,ERSE>
	SS	<ITH,VA,EVE,IE,GO,CIO,ETTE,ACT,ANT,OPE,USH,URT,ARB>

	MAGSZ3==.-MAGTB3	;NUMBER OF WORDS
	SUBTTL	DATA AREA



GOD:	XWD	500000,GODUSR	;USER NUMBER WHICH IS GODLY
CMDTAB:	BLOCK	CMDLEN+1	;ROOM FOR BUILDING OF COMMAND TABLE
PDL:	BLOCK	PDLSIZ		;STACK
DORTAB:	BLOCK	DIRMAX		;WHICH DIRECTIONS A TYPE OR DOOR IS ON
TMPBUF:	BLOCK	10		;TEMPORARY STRING USAGE
OUTPTR:	BLOCK	1		;BYTE POINTER INTO STORAGE AREA
OUTBUF:	BLOCK	^D100		;STORAGE FOR OUTPUT WHILE FILE LOCKED
OUTOVR:	BLOCK	1		;OVERFLOW FLAG
OUTTMP:	BLOCK	1		;TEMPORARY USE FOR OUTPUT
BUFF:	BLOCK	<COLMAX/5>+5	;TERMINAL OUTPUT BUFFER
BUFOVR:	BLOCK	1		;OVERFLOW FLAG
BUFPTR:	BLOCK	1		;BYTE POINTER INTO BUFFER
FULADR:	BLOCK	1		;ADDRESS IN BUFFER TO KNOW WHEN IT'S FULL
ENDLTR:	BLOCK	1		;POINTER TO LAST LETTER IN BUFFER
BEGWRD:	BLOCK	1		;POINTER TO FIRST LETTER OF THIS WORD
ENDWRD:	BLOCK	1		;POINTER TO LAST LETTER OF PREVIOUS WORD
MYJOB:	BLOCK	1		;MY JOB NUMBER
MYNUM:	BLOCK	1		;MY PLAYER NUMBER
MAXADR:	BLOCK	1		;HIGHEST ADDRESS IN FILE TO SEARCH ON
TEMP:	BLOCK	1		;TEMPORARY USE
PLURTM:	BLOCK	2		;TEMPORARY USE FOR PLURNM ROUTINE
TRETMP:	BLOCK	1		;TEMPORARY USE DURING TREASURE BUILDING
MOVDIR:	BLOCK	1		;DIRECTION TO MOVE IN
MOVLNK:	BLOCK	1		;LINK WORD FOR DESIRED MOVE
BLDDIR:	BLOCK	1		;DIRECTION TO BUILD IN
BLDLNK:	BLOCK	1		;ADDRESS OF LINK WORD TO BUILD FROM
BLDTYP:	BLOCK	1		;TYPE OF DOOR TO BUILD
BLDLVL:	BLOCK	1		;LEVEL OF ROOM TO BE BUILT
DORDIR:	BLOCK	1		;DIRECTION CREATING DOORS ON
DORDIC:	BLOCK	1		;NUMBER OF DOORS LEFT TO CHECK FOR
CHCTOT:	BLOCK	1		;TOTAL CHANCE FOR DOORS
CHCTAB:	BLOCK	DORNUM		;TABLE OF CHANCES FOR DOORS
TGTLOC:	BLOCK	1		;COORDINATES OF A TARGET ROOM
TGTDIR:	BLOCK	1		;DIRECTION TO LOOK FOR TARGET ROOM
TGTMAT:	BLOCK	1		;ROOM WHICH EXISTS AT TARGET ADDRESS
TGTNMT:	BLOCK	1		;ROOM WHICH EXISTS NEAR TARGET ADDRESS
TGTTYP:	BLOCK	1		;TYPE OF DOOR TO FIND
MONTYP:	BLOCK	1		;KIND OF MONSTER BEING ATTACKED
ITMWNT:	BLOCK	2		;ITEM TYPE AND AMOUNT WANTED
UUOARG:	BLOCK	1		;WORD POINTED TO BY AN LUUO
PTHTMP:	BLOCK	1		;USED TO MANIPULATE PATHS
PTHNAM:	BLOCK	1		;PATH NAME BEING ADDED
PTHBYT:	BLOCK	1		;BYTE POINTER INTO CURRENT PATH
DRPCNT:	BLOCK	1		;AMOUNT OF TREASURE BEING DROPPED
RANNUM:	BLOCK	1		;LAST PRODUCED RANDOM NUMBER
MSGJFN:	BLOCK	1		;JFN FOR MESSAGE FILE
MSGTIM:	BLOCK	1		;TIME MESSAGE FILE LAST WRITTEN
PLTNUM:	BLOCK	1		;NUMBER OF ROOMS IN PLOT
ITMCNT:	BLOCK	1		;COUNTER FOR ITEM TYPEOUT
LSTFLG:	BLOCK	1		;WHETHER OR NOT TO LIST ONLY OURSELF
RSTMAX:	BLOCK	1		;HOW MUCH TO REST UP TO
RSTMOV:	BLOCK	1		;NUMBER OF MOVES TAKEN TO REST
ERRTXT:	BLOCK	1		;ADDRESS OF ERROR TEXT
ERRXCT:	BLOCK	1		;INSTRUCTION TO EXECUTE DURING ERROR
MYUSER:	BLOCK	1		;MY USER NUMBER
PLYUSR:	BLOCK	1		;USER NUMBER WE ARE PLAYING AS
FILJFN:	BLOCK	1		;JFN FOR THE DATA FILE
LISCNT:	BLOCK	1		;NUMBER OF ELEMENTS IN A LIST
LISOLD:	BLOCK	1		;PREVIOUS ELEMENT IN A LIST
SAYIDX:	BLOCK	1		;INDEX INTO SAYING TABLE
PTHCNT:	BLOCK	1		;NUMBER OF ENTRIES IN A PATH
MOVPTR:	BLOCK	1		;BYTE POINTER INTO MOVLST TABLE
MOVLST:	BLOCK	MOVMAX+1	;TABLE OF MOVES TO BE MADE
FILNAM:	ASCII	/PS:<GAMES>CAVE.DAT;P776060/	;FILE NAME
	BLOCK	^D20		;ROOM FOR PATCHING NAME
TXTNAM:	ASCII	/PS:<GAMES>CAVE.TXT/	;MESSAGE FILE NAME
	BLOCK	^D20		;ROOM FOR PATCHING
SAVEP:	BLOCK	1		;STORAGE OF STACK POINTER
MAGTXT:	BLOCK	^D20		;CONTAINS A MAGIC PHRASE
TXTBUF:	BLOCK	TXTLEN/5+1	;BUFFER FOR COMMAND JSYS
ATMBUF:	BLOCK	TXTLEN/5+1	;BUFFER FOR ATOM BUFFER
DEFBUF:	BLOCK	1		;DEFAULT FIELD BUFFER FOR PLOT COMMAND
RMGENS:	BLOCK	2		;ROUTINES TO CALL FROM GENRMS
;PLOTTING VARIABLES.


SCALE:	BLOCK	1		;SCALE FACTOR
PJFN:	BLOCK	1		;JFN FOR THE PLOTTER
MININC:	BLOCK	1		;INCREMENT TO MINOR AXIS PER UNIT OF MAJOR AXIS
OLDPEN:	BLOCK	1		;LAST PEN STATE WE SENT
TWODIR:	BLOCK	2		;TWO DIRECTIONS MAKING UP OUR LINE
PLTCNT:	BLOCK	1		;COUNT OF BYTES LEFT TO WRITE IN BUFFER
PLTPTR:	BLOCK	1		;BYTE POINTER TO LAST BYTE WRITTEN
PLTPGN:	BLOCK	1		;JFN,,PAGE # OF PAGE WE'RE WRITING
PLTTOT:	BLOCK	1		;TOTAL NUMBER OF BYTES WE'VE WRITTEN SO FAR


;THE FOLLOWING GROUPS OF DATA SHOULD REMAIN CONTIGUOUS, SINCE THEY ARE
;REFERENCED BY DMOVES, ETC.


XMIN:	BLOCK	1		;LIMITS FOR PLOTTING, X AND Y MINS AND MAXES
XMAX:	BLOCK	1		;  ..

YMIN:	BLOCK	1		;  ..
YMAX:	BLOCK	1		;  ..

OLDIX:	BLOCK	1		;LAST INCREMENTAL X LOCATION
OLDIY:	BLOCK	1		;LAST INCREMENTAL Y LOCATION

X:	BLOCK	1		;FLOATING-POINT X COORDINATE OF CURRENT ROOM
Y:	BLOCK	1		;FLOATING-POINT Y COORDINATE OF CURRENT ROOM



	END	CAVE