;LIFE PROGRAM FOR THE VDM
;	BY WARD CHRISTENSEN
;
;THANKS TO:
;	CAREY TYLER SCHUG
;FOR THE ALGORITHM OF ADDING 1 TO EACH CELL
;AROUND A LIVE ONE, INSTEAD OF COUNTING
;LIVE CELLS AROUND EACH CELL.
;
;	BOB VAN VALZAH
;FOR SUGGESTING "INR M INSTEAD OF "ADI 10"
;FOR KEEPING TRACK OF THE NEXT GENERATION.
;ALSO FOR SUGGESTING THE RANDOM MUTATIONS
;(R) COMMAND. 
;
;	RANDY SUESS
;FOR SUGGESTING THE SPEED FUNCTION.
;
;	--MODS LOG--
;
;	10/24/79
;ORIGINALLY WRITTEN BY WARD CHRISTENSEN
;
;	12/23/79
;PUT IN LOTS MORE COMMENTS, FOR CP/M U.G.
;
	ORG	100H
VDM	EQU	0CC00H
;VDMPORT	EQU	0C8H
VDMPORT	EQU	0FEH
CR	EQU	0DH
LF	EQU	0AH
;MAKE FOLLOWING ' ' IF YOU HAVE NO ERASE CHAR.
;IT'S USED ONLY IN THE HELP FUNCTION, SO IS NOT
;CRITICAL
;ERASE	EQU	1AH	;SCREEN ERASE CHAR
ERASE	EQU	20H	;SCREEN ERASE CHAR
CHAR	EQU	0  	;SCREEN CHAR
;
	JMP	START
;
INITMSG	DB	'LIFE8 AS OF 12/23/79',CR,LF
	DB	'Type ? for help, X to exit'
	DB	cr,lf,cr,lf,1
;
START	XRA	A	;RESET VDM..
	OUT	VDMPORT	;..PORT
;
;INIT LOCAL STACK
;
	LXI	H,0
	DAD	SP
	SHLD	STACK
	LXI	SP,STACK
;
;SET UP BIOS VECTORS
;
	LHLD	1
	LXI	D,3
	DAD	D
	SHLD	VCONST+1
	DAD	D
	SHLD	VKEYIN+1
	DAD	D
	SHLD	VTYPE+1
;
	LXI	H,INITMSG
	CALL	MSGPRT
;
;COMMAND MODE
;
COMMAND	CALL	KEYIN
COMM2	CPI	'/'	! JZ	RANDOM
	CPI	'?'	! JZ	HELP
	CPI	'<'	! JZ	SAVE
	CPI	'>'	! JZ	RESTORE
	CPI	0DH	! JZ	SETRUN
	CPI	'C'	! JZ	CLEAR
	CPI	'I'	! JZ	INPUT
	CPI	'M'	! JZ	MOVERS
	CPI	'R'	! JZ	RANDHIT
	CPI	'S'	! JZ	SPEED
	CPI	'T'	! JZ	RTOGGLE
	CPI	'W'	! JZ	WTOGGLE
	CPI	'X'	! JZ	EXIT
	JMP	COMMAND
;
;TOGGLE THE SCREEN WRAP FLAG
;
WTOGGLE	LDA	WRAPFLG
	XRI	1
	STA	WRAPFLG
	JMP	COMMAND
;
;REQUEST RANDOM HIT EVERY TURN
;
RANDHIT	CALL	KEYIN	;GET DIGIT (OR ANY CHAR)
	ANI	0FH	;MAKE 0-F
	MOV	B,A
	ADD	A	;X2
	ADD	A	;X4
	ADD	B	;X5
	ADD	A	;X10
	MOV	B,A
	CALL	KEYIN	;GET NEXT DIGIT
	ANI	0FH
	ADD	B
	STA	RFLG	;NON ZERO FLAG
	JMP	COMMAND
;
;TOGGLE WHETHER RANDOM HITS ARE FLIP-FLOP
;	(OFF IF ON, ON IF OFF) OR JUST ON
;
RTOGGLE	LDA	RTOG
	XRI	1
	STA	RTOG
	MVI	A,'T'
	JZ	RTS	;SHOW TOGGLING
	MVI	A,'O'	;SHOW JUST ON
RTS	STA	VDM+3FFH
	JMP	COMMAND
;
;CLEAR THE VDM
;
CLEAR	LXI	H,VDM
	MVI	B,4	;4 PAGES
	MVI	A,' '	;CHAR TO CLEAR WITH
;
CLRLP	MOV	M,A	;CLEAR..
	INR	L	;..A..
	JNZ	CLRLP	;..PAGE
	INR	H	;NEXT PAGE
	DCR	B	;MORE PAGES?..
	JNZ	CLRLP	;..YES
	JMP	COMMAND
;
;INPUT MODE
;
INPUT	LXI	H,VDM+512+32 ;CENTER OF SCREEN
	LXI	D,0	;DFLT MOVE DIR=0
;
MOVE	DAD	D
INPLP	MOV	A,M	;TURN..
	XRI	80H	;..ON..
	MOV	M,A	;..CURSOR
	CALL	KEYIN	;GET A CHAR
	PUSH	PSW	;TURN..
	MOV	A,M	;..OFF..
	XRI	80H	;..THE..
	MOV	M,A	;..CURSOR
	POP	PSW
	CPI	'1'	;REPEAT REQUEST?
	JC	N1	;..NO..
	CPI	'9'+1	;..HI LIMIT TEST..
	JC	REPEAT	;..YES, REPEAT
N1	CPI	' '	;REQUEST TO FLIP BIT?
	JZ	TOGGLE	;..YES, TOGGLE IT
	CPI	'C'	;CLEAR?
	JZ	CLEAR
	LXI	D,64
	CPI	'J'	;DOWN 1?
	JZ	MOVE
	LXI	D,-64
	CPI	'K'	;UP 1?
	JZ	MOVE
	LXI	D,-1
	CPI	'H'	;BACK 1?
	JZ	MOVE
	LXI	D,1
	CPI	'L'	;RIGHT 1?
	JZ	MOVE
	CPI	0DH	;RUN?
	JZ	SETRUN
	JMP	INPLP	;INVALID, TRY AGAIN
;
;TOGGLE THE BIT UNDER THE CURSOR
;
TOGGLE	MOV	A,M	;GET CHAR
	CMA
	ADI	' '+CHAR+1 ;FLIP IT
	MOV	M,A
	JMP	INPLP
;
;REPEAT DIRECTION 1-9 TIMES
;
REPEAT	SUI	'0'	;MAKE '1'-'9' INTO 1-9
	MOV	B,A	;SAVE IT
	MOV	A,M	;TURN..
	ANI	7FH	;..OFF..
	MOV	M,A	;..CURSOR
REPLP	DAD	D	;MOVE
	DCR	B	;DONE?..
	JNZ	REPLP	;..NO
	JMP	INPLP
;
;SAVE A SCREEN IN MEMORY
;
SAVE	CALL	GETSNO	;GET SCREEN NUMBER/ADDRESS
	LXI	D,VDM
	CALL	MOVESCR	;MOVE IT
	JMP	COMMAND
;
;RESTORE A SCREEN FROM MEMORY
;
RESTORE	CALL	GETSNO	;GET SCREEN NUMBER/ADDRESS
	LXI	D,VDM
	XCHG		;OPP. DIR. OF SAVE
	CALL	MOVESCR
	JMP	COMMAND
;
;GET A DIGIT, CONVERT IT TO A SAVED SCREEN ADDRESS
;
GETSNO	CALL	KEYIN	;GET THE #
	ANI	0FH	;MAKE BINARY
	ADD	A
	ADD	A
	ADD	A
	ADD	A	;A=16*A
	MOV	L,A
	MVI	H,0
	DAD	H	;*32
	DAD	H
	DAD	H
	DAD	H	;*256
	DAD	H
	DAD	H	;*1024
	LXI	D,SCRMEM ;BASE ADDR OF SAVED SCREENS
	DAD	D
	RET		;SCREEN ADDR IN HL
;
;---->	MOVESCR MOVES 1 SCREEN FROM DE TO HL
;
MOVESCR	LXI	B,1024 ;SCREEN SIZE
MSLP	LDAX	D
	INX	D
	MOV	M,A
	INX	H
	DCX	B
	MOV	A,B
	ORA	C
	JNZ	MSLP
	RET
;
;SETRUN - SETS UP AND RUNS
;
SETRUN	LXI	H,VDM
	LXI	D,WORK
	MVI	B,4
SETLOW	MVI	C,0	;DEAD
	MOV	A,M	;GET SCREEN CHAR
	CPI	' '	;DEAD?
	JZ	SETL	;YES, SET IT
	CPI	'+'	;PAST GENERATION?
	JZ	SETL
	MVI	C,80H	;LIVE CELL IS 80H
SETL	MOV	A,C	;GET 0 OR 80H
	STAX	D	;SAVE IN WORK
	INR	L	;NEXT CHAR IN PAGE
	INR	E	; "	"	"
	JNZ	SETLOW	;END OF PAGE?
	INR	H	;NEXT PAGE
	INR	D	;  "	"
	DCR	B	;MORE PAGES?..
	JNZ	SETLOW	;..YES, LOOP.
;
;LOW MEMORY MATRIX IS BUILT - 
;INIT GENERATION COUNTER
;
	LXI	H,COUNT
	MVI	B,10
	MVI	A,' '
CCLR	MOV	M,A
	INX	H
	DCR	B
	JNZ	CCLR
;
;"BLAST" THE TOP AND BOTTOM, LEFT AND RIGHT
;
RUN	LXI	H,WORK
	PUSH	H
;	CALL	CLRLINE	;FOUND BEST NOT TO DO THIS
	POP	H
	LDA	WRAPFLG	;WRAP AROUND?
	ORA	A
	JZ	NOWRAP
	CALL	CLRCOL
	LXI	H,WORK+63
	CALL	CLRCOL
NOWRAP	LXI	H,WORK+15*64
;	CALL	CLRLINE	;FOUND BEST NOT TO.
;
;ZERO # OF CELLS
;
	LXI	H,ALIVE
	MVI	B,5
	MVI	A,' '
BALIVE	MOV	M,A
	INX	H
	DCR	B
	JNZ	BALIVE
	CALL	MOVEM	;POSITION MOVERS
	CALL	POSTS	;SET THE POST
;
;DO SPEED DELAY
;
	LDA	SPDVAL
	ADD	A
	JZ	FAST	;IT'S ZERO ANYWAY
	ADD	A
	ADD	A
	ADD	A	;TIMES 16
	MOV	H,A
	MVI	L,0
DELAY	DCX	H
	MOV	A,H
	ORA	L
	JNZ	DELAY
FAST	LXI	H,WORK+64
	LXI	B,-65	;INIT THINGS IN REGS..
	LXI	D,62	;..FOR SPEED
;
CALC	MOV	A,M
	ORA	A	;HI BIT ON = ALIVE
	JP	NOADD8
;
;ADD 1 TO THE 8 AROUND A LIVE CELL
;
	PUSH	H
	DAD	B	;-65
	INR	M	;UPPER LEFT
	INX	H
	INR	M	;UPPER MIDDLE
	INX	H
	INR	M	;UPPER RIGHT
;
	DAD	D	;+62
	INR	M	;LEFT MIDDLE
	INX	H	;SKIP MID-MID
	INX	H
	INR	M	;RIGHT MIDDLE
;
	DAD	D	;+62 TO BOTTOM LINE
	INR	M	;LOWER LEFT
	INX	H
	INR	M	;LOWER MIDDLE
	INX	H
	INR	M	;LOWER RIGHT
	LXI	H,ALIVE+3
	CALL	ADD1
	POP	H
NOADD8	INR	L	;NEXT CELL IN PAGE
	JNZ	CALC	;
	INR	H	;NEXT PAGE
	MOV	A,H	;SEE IF DONE
	CPI	4+(WORK/256)
	JNZ	CALC
;
;GOT NEXT GENERATION - SHOW IT
;
	CALL	SHOW
	CALL	CONST	;KEY PRESSED?
	JZ	RUN	;NO, RUN
;
;---->	END OF GENERATION
;
	CALL	KEYIN	;GET THE CHAR
	CPI	'+'
	JZ	TOGGEN2	;TOGGLE GENERATION 2
	CPI	'_'
	JZ	TOGBIR	;TOGGLE BIRTH FLAG
	CPI	'A'
	JZ	TOGMOVE	;TOGGLE SINGLE MOVER
	CPI	' '
	JZ	TOGPOST
	CPI	'H'
	JZ	POSTL	;LEFT
	CPI	'J'
	JZ	POSTD	;DOWN
	CPI	'K'
	JZ	POSTU	;UP
	CPI	'L'
	JZ	POSTR	;RIGHT
	CPI	'0'
	JC	COMM2	;NOT SPEED REQ
	CPI	'9'+1
	JC	SETSPD
	JMP	COMM2
;
;TOGGLE GENERATION 2 - CAUSES '+' TO APPEAR ON
;SCREEN FOR CELLS IN THE "PREVIOUS GENERATION"
;(JUST FOR ALL YOU REINCARNATIONISTS OUT THERE)
;
TOGGEN2	LXI	H,PAST+1
	MVI	A,'+'+' '	;<-- YES, THAT'S RIGHT
	SUB	M
	MOV	M,A	;TOGGLE BETWEEN '+' AND ' '
	JMP	RUN
;
;TOGGLE THE REV VIDEO FOR BIRTHS FLAG.
;
TOGBIR	LDA	BIRTH+1
	XRI	80H
	STA	BIRTH+1
	JMP	RUN
;
;TOGGLE POSTS ON/OFF
;
TOGPOST	LXI	H,POSTCHR
	MVI	A,' '+CHAR
	SUB	M
	MOV	M,A
	JMP	RUN
;
;MOVE POSTS, UP, DOWN, LEFT, RIGHT
;
POSTU	LDA	POST	;GET VERT POST POS.
	DCR	A
	STA	POST
	JMP	RUN
POSTD	LDA	POST
	INR	A
	STA	POST
	JMP	RUN
POSTL	LDA	POST+1	;GET HORIZ POST POS
	DCR	A
	STA	POST+1
	JMP	RUN
POSTR	LDA	POST+1
	INR	A
	STA	POST+1
	JMP	RUN
;
;SET SPEED DURING RUN, CONTINUE RUNNING
;
SPEED	CALL	KEYIN	;GET THE SPEED
SETSPD	ANI	0FH	;SAVE 4 BITS
	STA	SPDVAL
	JMP	RUN	;..THEN RUN
;
;TOGGLE SINGLE BIT OF MOVER ON/OFF
;DURING RUN
;
TOGMOVE	LDA	NMOVERS
	XRI	1
	STA	NMOVERS
	JMP	RUN
;
;SHOW THE RESULTS
;
SHOW	LXI	D,WORK
	LXI	H,VDM
	MVI	B,4
	MVI	C,' '	;DEAD CELL
SHOWLP	LDAX	D
	ORA	A
	JZ	DEAD
	CPI	80H	;LIVE IN PAST GEN?
	JZ	PAST	;PAST GENERATION ONLY
	CPI	82H	;LIVE W/2 NEIGHBORS?
	JZ	LIVE
	CPI	3	;DEAD, 3 NEIGHBORS?
	JZ	BIRTH	;A NEW BOUNCING BABY ZORK
	CPI	83H	;LIVE, 3 NEIGHBORS?
	JZ	LIVE
	ORA	A
	JM	PAST	;WAS ALIVE?
	JMP	DEAD
;
BIRTH	MVI	M,CHAR
	JMP	LIVE2
;
LIVE	MVI	M,CHAR
LIVE2	MVI	A,80H
	JMP	STCELL
;
;PAST GENERATION WAS ALIVE, STORE '+' OR ' '
;
PAST	MVI	M,' '	;GET CHAR (MOD BY "+" COMMAND)
	JMP	DEAD2
;
DEAD	MOV	M,C	;MOVE IN ' '
DEAD2	XRA	A
STCELL	STAX	D
	INR	L	;MORE IN PAGE?
	INR	E
	JNZ	SHOWLP
	INR	H	;NEXT PAGE
	INR	D
	DCR	B	;DONE?
	JNZ	SHOWLP
;
;PUT IN A RANDOM HIT
;
	LDA	RFLG	;RANDOM HIT REQ?
	ORA	A
	CNZ	RHIT	;RANDOM HIT
;
;COUNT THE GENERATIONS
;
	LXI	H,COUNT+9
	CALL	ADD1	;ADD IN 1
;
;SHOW THE GENERATION COUNT
;
SHOWCT	LXI	H,VDM+3FFH
	LXI	D,COUNT+9
	MVI	B,14
CTMVLP	LDAX	D
	MOV	M,A
	DCX	D
	DCX	H
	DCR	B
	JNZ	CTMVLP
	RET
;
;ROUTINE TO ADD 1 TO AN ASCII NUMBER
;
ADD1	MOV	A,M
	ORI	'0'	;CONV ' ' TO '0'
	INR	A
	MOV	M,A
	CPI	'9'+1	;CARRY?
	RNZ		;..NO, RETURN
	MVI	M,'0'	;STORE 0,..
	DCX	H	;..BACK UP
	JMP	ADD1	;..BUMP HIGHER DIGIT
;
;RANDOMLY HIT THE MATRIX
;
RHIT	LDA	RFLG
	MOV	B,A	;COUNT
RHLP	CALL	RAND	;GET ROW
	ANI	0F0H	;MAKE 4 BIT NUMBER * 16
	MOV	L,A
	MVI	H,0
	DAD	H	;*32
	DAD	H	;*64
	CALL	RAND	;CALL TWICE TO MIX 'EM UP
	CALL	RAND	;GET COL
	ANI	3FH	;SAVE DISPL
	ADD	L	;ADD IN (CAN'T CARRY)
	MOV	L,A
	XCHG
	LXI	H,WORK	;TO BASE
	DAD	D	;ADD DISPL
	LDA	RTOG	;SEE IF TOGGLING
	ORA	A
	JZ	TOG	;..YES
;
;STORE CHAR ON, INSTEAD OF JUST TOGGLING
;
	MVI	M,80H	;NOT TOGGLE, JUST TURN ON
	LXI	H,VDM
	DAD	D
	MVI	M,CHAR
	JMP	RHCONT
TOG	MVI	A,80H	;TOGGLE THE CELL
	XRA	M
	MOV	M,A
	LXI	H,VDM
	DAD	D	;FLIP ON THE SCREEN, TOO
	MVI	A,' '+CHAR
	SUB	M
	MOV	M,A
RHCONT	DCR	B
	JNZ	RHLP
	RET		;FROM RHIT
;
;CLEAR LINE OF VDM (I BELIEVE I NO LONGER USE THIS)
;
CLRLINE	MVI	A,0 
	MVI	B,64
CLRLLP	MOV	M,A
	INX	H
	DCR	B
	JNZ	CLRLLP
	RET		;FROM CLRLINE
;
;CLEAR A COLUMN OF THE VDM - USED
;WHEN NOT WRAPPING LEFT/RIGHT
;
CLRCOL	LXI	D,64
	MVI	A,0 
	MVI	B,16
CLRCLL	MOV	M,A
	DAD	D
	DCR	B
	JNZ	CLRCLL
	RET		;FROM CLRCOL
;
;CP/M CONSOLE STAUS TEST
;
CONST	PUSH	B
	PUSH	D
	PUSH	H
VCONST	CALL	$-$
	POP	H
	POP	D
	POP	B
	ORA	A	;SET 0 IF NO CHAR
	RET
;
;CP/M KEYBOARD INPUT ROUTINE
;
KEYIN	PUSH	B
	PUSH	D
	PUSH	H
VKEYIN	CALL	$-$
	ANI	7FH
	POP	H
	POP	D
	POP	B
	STA	VDM+3FFH	;"ECHO" CHAR
	CPI	61H	;LOWER CASE A?
	RC
	ANI	5FH	;MAKE UPPER CASE
	RET		;(TURNS DEL INTO "_")
;
;CP/M CHARACTER OUTPUT
;
TYPE	PUSH	B
	PUSH	D
	PUSH	H
	MOV	C,A
VTYPE	CALL	$-$
	POP	H
	POP	D
	POP	B
	RET
;
;EXIT, RETURNING TO CP/M
;
EXIT	LHLD	STACK
	SPHL
	RET
;
;RANDOM SCREEN FILL
;
RANDOM	CALL	KEYIN	;GET DENSITY
	ANI	0FH	;MAKE IT 0-F HEX
	MOV	C,A	;SAVE DENSITY
	LXI	H,VDM
RANFILL	CALL	RAND
	CALL	RAND
	ANI	0FH
	CMP	C	;THIS CELL?
	MVI	A,CHAR
	JNC	NSTORE	;NO
	MOV	M,A
NSTORE	INX	H
	MOV	A,H
	CPI	4+(VDM/256)
	JNZ	RANFILL
	JMP	COMMAND
;
;MOVERS:
;	ARE SINGLE CELLS WHICH STAY ALIVE,
;	AND MOVE ABOUT THE SCREEN.  WHEN
;	THEY TOUCH SOMETHING, THEY EFFECT IT,
;	BUT CONTINUE TO MOVE, UNDYING.
;
MOVERS	CALL	KEYIN	;GET HOW MANY
	ANI	0FH
	STA	NMOVERS	;SET COUNT
	JZ	COMMAND	;NONE
;
;GOT REQUEST FOR MOVERS, RANDOMLY SET UP
;EACH ONES POSITION, AND DIRECTION.
;
	MOV	B,A	;SAVE COUNT
	LXI	H,NMOVERS+1	;TO TABLE
MOVESET	CALL	DISP	;GET INITIAL DIRECTION
	MOV	M,A
	INX	H
	CALL	RAND	;GET ROW
	RAR ! RAR ! RAR	;MIX THINGS UP
	ANI	0FH
	MOV	M,A	;SAVE ROW
	INX	H	;POINT TO COLUMN DISP
	CALL	DISP
	ADD	A	;X2
	MOV	C,A
	CALL	DISP
	ADD	C
	MOV	M,A	;STORE COL DISP
	INX	H
	CALL	RAND	;GET COLUMN
	ANI	3FH	;ISOLATE COLUMN
	MOV	M,A
	INX	H	;TO NEXT ROW DISP
	DCR	B	;MORE?
	JNZ	MOVESET	;..YES, LOOP
	JMP	COMMAND	;..NO RETURN
;
;MOVE THE RANDOM MOVERS	(IF ANY)
;
MOVEM	LDA	NMOVERS
	ORA	A
	RZ		;NONE
	LXI	H,NMOVERS+1 ;POINT TO TABLE
	MOV	B,A	;SAVE COUNT
MOVEMLP	MOV	A,M	;GET ROW DISP
	INX	H	;TO ROW
	ADD	M	;MODIFY ROW
	JM	BADROW	;DON'T GO <0
	CPI	15
	JC	ROWOK
BADROW	DCX	H	;BACK TO DISPL
	CALL	DISP
	MOV	M,A
	INX	H	;BACK TO ROW
	MOV	A,M	;GET OLD
	JMP	OLDROW	;USE OLD THIS TIME
ROWOK	MOV	M,A	;SAVE NEW POSITION
OLDROW	XCHG		;SAVE HL
	MOV	L,A
	MVI	H,0	;SETUP FOR MULT
	DAD	H
	DAD	H
	DAD	H
	DAD	H
	DAD	H
	DAD	H	;X64
	XCHG		;HL BACK
;
	INX	H	;TO COL DISP
	MOV	A,M
	INX	H
	ADD	M	;MODIFY ROW
	JM	BADCOL	;DON'T GO < 0
	CPI	63
	JC	COLOK
;
BADCOL	DCX	H	;BACK TO DISPL
	CALL	DISP
	ADD	A	;X2
	MOV	C,A
	CALL	DISP
	ADD	C
	MOV	M,A
	INX	H	;BACK TO COL
	MOV	A,M	;GET OLD
	JMP	OLDCOL	;USE OLD THIS TIME
COLOK	MOV	M,A	;SAVE NEW POSITION
OLDCOL	INX	H	;TO NEXT ROW DISP
	ADD	E	;CALC POS
	MOV	E,A
	PUSH	H
	LXI	H,VDM
	DAD	D
	MVI	A,'A'-1
	ADD	B	;'A'=FIRST, ETC
	MOV	M,A
	LXI	H,WORK
	DAD	D
	MVI	M,80H	;SET LIVE
	POP	H
	DCR	B
	JNZ	MOVEMLP
	RET
;
;CALCULATE A DISPLACEMENT FOR MOVERS,
;	-1, 0, OR 1
;
DISP	CALL	RAND	;MIX 'EM UP
	CALL	RAND	;GET A DIRECTION
	ANI	3
	JZ	DISP	;MAKE IT 1, 2, 3
	SUI	2	;MAKE IT -1, 0, 1
	JZ	DISP	;TRY AGAIN IF 0
	RET
;
;POST IS A NEVER DYING, NEVER MOVING CELL,
;WHICH IS CONTROLLABLE IN RUN MODE AS IF
;YOU WERE IN INPUT MODE
;
POSTS	LDA	POSTCHR
	CPI	' '
	RZ
	LDA	POST
	MOV	L,A
	MVI	H,0
	DAD	H
	DAD	H
	DAD	H
	DAD	H
	DAD	H
	DAD	H	;X64
	LDA	POST+1	;GET COLUMN
	ADD	L
	MOV	L,A
	XCHG
	LXI	H,VDM
	DAD	D
	MVI	M,CHAR
	LXI	H,WORK
	DAD	D
	MVI	M,80H
	RET
;
;RANDOM NUMBER GENERATOR,
;(SHIFT AND EXCLUSIVE-OR TYPE)
;
RAND	PUSH	H
	PUSH	B
	LXI	H,RNO
	PUSH	H
	MVI	B,7	;LENGTH
	ORA	A
RANDLP	MOV	A,M
	RAL
	MOV	M,A
	INX	H
	DCR	B
	JNZ	RANDLP
	DCX	H	;TO LAST DIGIT
	RAL
	RAL
	XRA	M
	RLC
	ANI	1
	POP	H
	ORA	M
	MOV	M,A
	POP	B
	POP	H
	RET
;
;HELP MODE - PRINT MENU, ACCEPT SINGLE
;CHAR COMMAND FOR DETAIL HELP
;
HELP	MVI	A,ERASE	;WARD'S SCREEN CLEAR
	CALL	TYPE
	LXI	H,HMSG
	CALL	MSGPRT
	CALL	KEYIN
	MOV	B,A	;SAVE FOR MATCH
	LXI	H,HMSG
HFIND	MOV	A,M
	ORA	A
	JZ	COMMAND	;NOT FOUND
	DCR	A
	INX	H
	JNZ	HFIND
;
;AT CHAR.  SEE IF IT MATCHES
;
	MOV	A,B
	CMP	M
	JNZ	HFIND
	INX	H
	MVI	A,ERASE
	CALL	TYPE
	CALL	MSGPRT	;PRINT IT
	LXI	H,MSG2
	CALL	MSGPRT
	JMP	COMMAND
;
;PRINT MSG POINTED TO BY HL, 1 TERMINATES
;
MSGPRT	MOV	A,M
	CALL	TYPE
	INX	H
	MOV	A,M
	CPI	1
	RZ
	JMP	MSGPRT
;
MSG2	DB	cr,lf,'..back to command mode now.',cr,lf
	db	'type ? again if required.',cr,lf,1
;
HMSG	db	'Command: /* command mode */',cr,lf
	db	' C/R  goto Run',cr,lf
	db	' /  goto Random fill',cr,lf
	db	' <  goto Save',cr,lf
	db	' >  goto Restore',cr,lf
	db	' C  goto Clear',cr,lf
	db	' I  goto Input',cr,lf
	db	' M  goto Movers',cr,lf
	db	' R  goto Random mutate',cr,lf
	db	' S  goto Set speed',cr,lf
	db	' T  goto Toggle',cr,lf
	DB	' W  goto Wrap',cr,lf
	db	' X  exit to CP/M',cr,lf
	db	'More help? Type command char, '
	db	'or space to return to command.',cr,lf
;
	DB	1,'S'
	DB	'Set speed:',cr,lf
	db	' 0-9 Set speed (0=fastest)',cr,lf
	db	' goto Command',cr,lf
;
	db	1,'W'
	db	'Wrap:',cr,lf
	db	' Toggle the screen wrap (l/r) bit'
	db	' goto Command.',cr,lf
;
	db	1,'C'
	db	'Clear:',cr,lf
	db	' Clear the screen.',cr,lf
	db	' Goto command.',cr,lf
;
	db	1,'I'
	db	'Input: /* input mode */',cr,lf
	db	' (space) toggle char under cursor.',cr,lf
	db	' J down  1; goto Input',cr,lf
	db	' H back  1; goto Input',cr,lf
	db	' K up    1; goto Input',cr,lf
	db	' L right 1 ;goto Input',cr,lf
	db	' 0-9 repeat prev direction '
	db		'n times; goto Input',cr,lf
	db	' C/R R goto Run',cr,lf
	db	' C goto Clear',cr,lf
	db	'   goto Input',cr,lf
;
	db	1,'X'
	db	' X returns immediately to CP/M',cr,lf
;
	db	1,cr
	db	'Run: /* run mode */',cr,lf
	db	' A toggle single mover on/off',cr,lf
	db	' 0-9 set speed',cr,lf
	DB	' + toggle death show flag',cr,lf
	db	' _ toggles birth show flag',cr,lf
	db	' (space) toggles "post" (undying cell) '
	db	'on/off',cr,lf
	db	' H, J, K, L move the "post" as if in '
	db	'input mode',cr,lf
	db	' (any char: goto command '
	db	'with that char)',cr,lf
;
	db	1,'/'
	db	'Random fill:',cr,lf
	db	' Accept a digit, ANI 0FH.',cr,lf
	db	' Fill screen randomly, density n/16.',cr,lf
	db	' goto Command.',cr,lf
;
	db	1,'M'
	db	'Movers:',cr,lf
	db	' Accept a digit, which is how many',cr,lf
	db	' movers on screen per generation.',cr,lf
	db	' goto Command.',cr,lf
;
	db	1,'<'
	db	'Save:',cr,lf
	db	' Accept a digit.',cr,lf
	db	' Save current screen under that number'
	db	cr,lf,' Goto command.',cr,lf
;
	db	1,'>'
	db	'Restore:',cr,lf
	db	' Accept a digit.',cr,lf
	db	' Restore screen under that number'
	db	cr,lf,' Goto command.',cr,lf
;
	db	1,'T'
	db	'Toggle:',cr,lf
	db	' Toggle random mutation switch,',cr,lf
	db	' to toggle (=T) or only turn on (=O)'
	db	cr,lf,' when mutating.',cr,lf
	db	' (Bottom corner shows the T or O)'
	db	cr,lf,cr,lf
;
	db	1,'R'
	db	'Random mutate',cr,lf
	db	' Accept a 2 digit number.',cr,lf
	db	' Store as # of random hits per cycle.',cr,lf
	db	' goto Command.',cr,lf,1,0
;
SPDVAL	DB	0	;SPEED (0=FAST)
WRAPFLG	DB	0	;WRAP SCREEN?
RNO	DB	1,0FEH,0AFH,45,34,26,18,45,27
	DB	1,2,3,4,5
;
RTOG	DB	0	;TOGGLE RANDOM OR JUST ON?
RFLG	DB	0	;1 IF RANDOM
;
POSTCHR	DB	' '
POST	DB	8,32	;UNMOVABLE OBJECT
;
;MOVERS TABLE (FOLLOWS NMOVERS)
;	ROW DISP, ROW, COL DISP, COL
;
NMOVERS	DB	0	;# OF MOVERS
	DB	3,1,1,1	;DEFAULT FIRST MOVER
	DS	4*15	;TABLE FOR 15 MOVERS
;
ALIVE	DS	5
COUNT	DS	10
;
	DS	100
STACK	DS	2
;
WORK	ORG	($+255) AND 0FF00H
	DS	1024	;1 SCREEN
	DS	64	;LAST LINE GARBAGE HERE
;
;DEFINE MEMORY FOR UP TO 16 SAVED SCREENS
;
SCRMEM	EQU	$

