home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
ftp.barnyard.co.uk
/
2015.02.ftp.barnyard.co.uk.tar
/
ftp.barnyard.co.uk
/
cpm
/
walnut-creek-CDROM
/
BEEHIVE
/
GAMES
/
MAZEBLD.ARC
/
MAZEBLD.Z80
< prev
Wrap
Text File
|
1980-01-01
|
23KB
|
1,149 lines
; MAZE BUILDER
; BY IAN JOHNSTONE
; 13/9/87
;
ORG 100H
CALL PROLOG ;Relocate stack and pass control to MAIN
JP WARM ;Tidy up and exit
;
BEL EQU 7
CLS EQU 26
CR EQU 0DH
CTRLC EQU 3
LF EQU 0AH
TAB EQU 9
TBUF EQU 80H ;Default buffer
TFCB EQU 05CH ;Default TFCB
MAZE EQU 7000H ;Buffer to hold model of maze
SCREEN EQU 0F000H ;Start of video RAM
OFFSET EQU 8000H ;Offset from maze to screen
LASTLN EQU 0F730H ;Last line of screen
GRAPH EQU 0F810H ;Start of PCG RAM + 10H
MGRAPH EQU 80H ;Mask to convert digit to related graphic
DOT EQU 90H ; ditto but with dot in centre
;
WARM EQU 0
BDOS EQU 5
;
DIRIO EQU 6
GETCH EQU 1
LINEIN EQU 10
STATUS EQU 11
;
MAIN: CALL PRESS ;Press any key
MAIN2: CALL INIT ;Init & set up Graphics
CALL USERIN ;Get user input
CALL SETMAZE ;Set up Maze boundaries
CALL GSTART ;Select a random entry point into maze
CALL MOVE ;Random move thru Maze leaving trail of
;open cells until all cells opened
CALL CHOOSE ;Play maze game or view auto-escape
JP NZ,MAIN2 ;Round again if desired
RET ;Return to PROLOG
;
INIT: ;***** Initialise Maze
LD HL,MAZE ;Fill maze area with ones
LD (HL),1
LD DE,MAZE+1
LD BC,800H
LDIR
LD DE,GRAPH ;Write graphics into PCG area
LD HL,MAZDAT
LD BC,240
LDIR
LD DE,GRAPH+100H ;And into next page
LD HL,MAZDAT
LD BC,240
LDIR
LD B,15
LD HL,GRAPH+104H ;But put a dot in centre
LD DE,14
PUTDOT: LD A,(HL)
OR 8
LD (HL),A
INC HL
LD A,(HL)
OR 28
LD (HL),A
INC HL
LD A,(HL)
OR 8
LD (HL),A
ADD HL,DE
DJNZ PUTDOT
RET
MAZDAT: DB 129,129,129,129,129,129,129,129,129,129,255,0,0,0,0,0
DB 255,128,128,128,128,128,128,128,128,128,255,0,0,0,0,0
DB 128,128,128,128,128,128,128,128,128,128,255,0,0,0,0,0
DB 255,129,129,129,129,129,129,129,129,129,129,0,0,0,0,0
DB 129,129,129,129,129,129,129,129,129,129,129,0,0,0,0,0
DB 255,128,128,128,128,128,128,128,128,128,128,0,0,0,0,0
DB 128,128,128,128,128,128,128,128,128,128,128,0,0,0,0,0
DB 255,1,1,1,1,1,1,1,1,1,255,0,0,0,0,0
DB 1,1,1,1,1,1,1,1,1,1,255,0,0,0,0,0
DB 255,0,0,0,0,0,0,0,0,0,255,0,0,0,0,0
DB 0,0,0,0,0,0,0,0,0,0,255,0,0,0,0,0
DB 255,1,1,1,1,1,1,1,1,1,1,0,0,0,0,0
DB 1,1,1,1,1,1,1,1,1,1,1,0,0,0,0,0
DB 255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
DB 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
;
PROLOG: LD HL,0 ;Re-locate stack
ADD HL,SP ;Get stack pointer
LD (STAK),HL ;Save it
LD HL,STAK
LD SP,HL ;SP is now at STAK
CALL MAIN ;Exedcutre program
JP WARM ;Return to CP/M
DS 40H ;Buffer for stack
STAK: DW 0
;
USERIN: ;Get user input
LD DE,TBUF
CALL SETDMA
CALL RATE ;Get & save delay timer
CALL PRINT
DB CR,LF,LF,'Enter Width, Height (Max 76,20) '
DB CR,LF,LF,'On error will default to 30,12 ',0
CALL GETSTR ;Get user input
LD B,0 ;Digit counter
LD HL,TBUF+2
LD DE,WBUF
CALL ULP ;Read width parameter into WBUF
OR A
JR Z,DFLT ;Default if buffer empty
INC HL
LD DE,HBUF
LD C,B ;Save digit count
LD B,0;Clear counter
CALL ULP ;Read Height parameter into HBUF
LD HL,WBUF
CALL TOBNRY ;Convert ASCII width to binary
LD (WIDTH),A
OR A
JR Z,DFLT
CP 77
JR NC,DFLT ;Default if under- or over-size
LD HL,HBUF
LD C,B ;Count of height digits
CALL TOBNRY ;Now height
LD (HEIGHT),A
OR A
JR Z,DFLT
CP 21
JR NC,DFLT
JR USRX ;Exit to MAIN
DFLT: LD A,30 ;Put default parameters in buffers
LD (WIDTH),A
LD A,12
LD (HEIGHT),A
USRX: LD A,CLS
CALL PUTCH
RET
;
SPEED: DB 0
WIDTH: DW 0
HEIGHT: DW 0
;
ULP: ;Read contents of Input buff
LD A,(HL) ;HL -> start of text in buff
CP ' ' ;Skip blanks
JP NZ,ULP1
INC HL
JP ULP
ULP1: CP 0 ;Delimiter
RET Z
CP ',' ;Element seperator
RET Z
INC B ;Digit count
LD (DE),A ;DE -> width or height buff
INC DE
INC HL
JR ULP
;
WBUF: DW 0
HBUF: DW 0
;
TOBNRY: ;Convert 2 ASCII digits -> by HL to binary
XOR A
CP (HL)
RET Z ;Abort if buffer empty
DEC C ;C=digit count
JR Z,UUNITS
DEC C
JR Z,UTENS
JR TBNRX
UTENS: LD A,(HL) ;Multiply tens digit
AND 0FH ;Stripped of ASCII
ADD A,A ;by two
LD C,A
ADD A,A ;by 4
ADD A,A ;by 8
ADD A,C ;by 10
LD C,A
INC HL
UUNITS: LD A,(HL)
AND 0FH ;Strip ASCII from units digit
ADD A,C ;& add to 10 times tens
TBNRX: RET
;
SETMAZE: ;***** Set up maze in buffer and on screen
LD A,(WIDTH)
OR A ;Reset carry
RRA
LD L,A
LD H,0
LD (HALFW),HL ;Subtract half of width
LD DE,MAZE+40 ;From centre of top line
OR A
EX DE,HL
SBC HL,DE
LD A,(HEIGHT)
PUSH AF
OR A
RRA
LD B,A ;Subtract half of height
LD A,12 ;from half of maximum height
SUB B
LD B,A
LD DE,80
STM1: ADD HL,DE ;and "line feed" this many lines
DJNZ STM1
LD (CORNER),HL ;Record top left corner
POP BC ;get height - 1
DEC B
STM2: ADD HL,DE ;& calculate bottom left corner
DJNZ STM2
LD (BOTLEFT),HL
LD HL,(CORNER)
OR A
SBC HL,DE
PUSH HL ;Tab up to balance later "line feed"
LD A,(HEIGHT)
LD C,A
STM3: POP HL ;Fill maze area of maze buff with zeros
ADD HL,DE ;"line feed"
PUSH HL
LD A,(WIDTH)
LD B,A
STM4: LD (HL),0
INC HL
DJNZ STM4 ;Zero fill one line
DEC C
JR NZ,STM3 ;LF and zero another, till done
POP HL ;Clear stack
LD HL,(CORNER)
LD DE,OFFSET-80 ;Now do the screen
ADD HL,DE
LD DE,80
PUSH HL
LD A,(HEIGHT)
LD C,A
STM5: POP HL
ADD HL,DE
PUSH HL
LD A,(WIDTH)
LD B,A
STM6: LD (HL),'X'
INC HL
DJNZ STM6 ;Fill a line with 'X's
DEC C
JR NZ,STM5
POP HL
ADD HL,DE ;Point to South boundary
LD A,(WIDTH)
LD B,A
STM7: LD (HL),142
INC HL
DJNZ STM7 ;and draw a line
LD HL,(CORNER)
LD DE,OFFSET-80
ADD HL,DE ;Point to north boundary
LD A,(WIDTH)
LD B,A
STM8: LD (HL),139
INC HL
DJNZ STM8 ;and draw a line
LD HL,(CORNER)
LD DE,OFFSET-1 ;Point to top of West boundary
ADD HL,DE
LD DE,80
LD A,(HEIGHT)
LD B,A
PUSH BC
STM9: LD (HL),141
ADD HL,DE
DJNZ STM9 ;and draw a line
LD HL,(CORNER)
LD DE,OFFSET
ADD HL,DE
EX DE,HL
LD HL,(WIDTH)
ADD HL,DE ;point to top of east boundary
LD DE,80
POP BC
STM10: LD (HL),135
ADD HL,DE
DJNZ STM10 ;and draw a line
RET
;
HALFW: DW 0
HALFH: DW 0
CORNER: DW 0
BOTLEFT:DW 0
;
GSTART: ;Establish a random starting point
LD HL,GSTX
PUSH HL ;Establish a return address
LD A,4 ;Select a boundary for entry
CALL RAND ;Returns RND(4) + 1
DEC A ;1=N, 2=E, 3=S, 4=W
JR Z,RNORTH
DEC A
JR Z,REAST
DEC A
JR Z,RSOUTH
JR RWEST
GSTX: LD (RNDSTART),HL ;Record selected starting point
LD (HERE),HL ;twice
LD (HL),A ;Record direction code
ADD HL,DE ;DE=screen offset + offset to boundary
LD (HL),' ' ;Punch a hole in the boundary
LD (MZXIT),HL
RET
RNORTH: CALL RHORIZ ;Return RND(WIDTH-1)+1 in DE
LD HL,(CORNER)
LD A,2 ;Direction code for north
ADD HL,DE ;HL=starting point
LD DE,OFFSET-80 ;Point to border on screen
RET
RSOUTH: CALL RHORIZ
LD HL,(BOTLEFT)
LD A,8
ADD HL,DE
LD DE,OFFSET+80
RET
RHORIZ: LD A,(WIDTH)
DEC A
CALL RAND ;= RND(WIDTH-1)+1
LD E,A
LD D,0 ;= LD DE,A
RET
REAST: CALL RVERT ;Returns CORNER+RND(HEIGHT-1) LFs in HL
LD DE,(WIDTH)
DEC DE
LD A,4 ;Direction code for east
ADD HL,DE ;HL=starting point
LD DE,OFFSET+1 ;Point to screen border
RET
RWEST: CALL RVERT
LD A,16
LD DE,OFFSET-1
RET
RVERT: LD A,(HEIGHT)
DEC A
CALL RAND ;Returns RND(HEIGHT-1)+1 in A
LD B,A
LD HL,0
LD DE,80
RVT1: ADD HL,DE ;Multiply it by 80
DJNZ RVT1
LD DE,(CORNER)
ADD HL,DE ;& add to CORNER
RET
MZXIT: DW 0
;
MOVE: ;Move to an adjoining cell
LD DE,OFFSET ;Offset from maze to screen
LD HL,(HERE) ;Mark current cell on screen
ADD HL,DE
LD (HL),'*'
LD A,DIRIO ;Scan for ^C
LD DE,0FFH
CALL HLBDOS
OR A
CP CTRLC
JP NZ,MOVE0
POP HL ;Clear stack
RET ;Exit on ^C
MOVE0: CALL NEIGHB ;Returns B=count of legal moves in array LOTTO
JR NZ,MALL
INC B ;West move is legal so Inc count
LD (HL),3 ;& put west code in array
MALL: LD A,B
OR A
JP Z,BKTRK ;If no legal exit, try a backtrack
CALL RAND ;Select a legal move
CALL MKMOV ;and make it
MVBK: LD HL,(LAST) ;Put a dot graphic in previous cell
LD A,(HL)
RRA
AND 0FH
OR MGRAPH ;Mask for dot graphic
LD DE,OFFSET
ADD HL,DE
LD (HL),A ;Display dot
JP MOVE ;Try another move
;
NEIGHB: CALL GOVERN ;Delay loop
LD B,0 ;Count of legal exits
LD HL,LOTTO ;array " " "
PUSH HL
LD HL,(HERE)
LD DE,-80 ;Test cell to north
ADD HL,DE
LD A,(HL)
POP HL
OR A
JR NZ,ME ;Is vacant if zero, else try east
INC B ;so inc count
LD (HL),0 ;and put it in array (north=0)
INC HL
ME: PUSH HL ;now try east
LD HL,(HERE)
INC HL
LD A,(HL)
POP HL
OR A
JR NZ,MS ;If illegal, try south
INC B
LD (HL),1 ;put in array (east=1)
INC HL
MS: PUSH HL ;now try south
LD HL,(HERE)
LD DE,80
ADD HL,DE
LD A,(HL)
POP HL
OR A
JR NZ,MW
INC B
LD (HL),2 ;(south=2)
INC HL
MW: PUSH HL ;now try west
LD HL,(HERE)
DEC HL
LD A,(HL)
POP HL
OR A
RET
LOTTO: DB 0,0,0,0 ;Array of legal moves
LAST: DW 0 ;Location of last cell visited
;
MKMOV: LD HL,(HERE) ;Get current cell
LD (LAST),HL ;It's being superceded
LD B,A ;B=random choice
LD HL,LOTTO ;of array element
DEC HL
MKM1: INC HL ;Locate chosen element
DJNZ MKM1
LD A,(HL) ;Fetch it
OR A ;Zero=north
JR Z,MVNOR
DEC A ;1=east
JR Z,MVEAST
DEC A ;2=south
JR Z,MVSOU
LD HL,(HERE) ;else west
MVWEST: LD A,(HL)
OR 16 ;West code = 16
LD (HL),A ;So mark cell
DEC HL ;Now move west
LD (HERE),HL
LD (HL),4 ;We can move east from new cell
RET
MVNOR: LD HL,(HERE)
LD A,(HL)
OR 2 ;North code = 2
LD (HL),A
LD DE,-80
ADD HL,DE
LD (HERE),HL
LD (HL),8 ;We can move south from new cell
RET
MVEAST: LD HL,(HERE)
LD A,(HL)
OR 4 ;East code = 4
LD (HL),A
INC HL
LD (HERE),HL
LD (HL),16 ;We can move west from new cell
RET
MVSOU: LD HL,(HERE)
LD A,(HL)
OR 8 ;South code = 8
LD (HL),A
LD DE,80
ADD HL,DE
LD (HERE),HL
LD (HL),2 ;We can move north from new cell
RET
;
RATE: CALL PRINT
DB CLS,CR,LF,LF,TAB,TAB,TAB,'RANDOM MAZE BUILDER'
DB CR,LF,LF,'Do you want',CR,LF,TAB,'1. Fast',CR
DB LF,TAB,'2. Medium',CR,LF,TAB,'3. Slow ',0
CALL DIRIN ;Direct input
CP CTRLC
JP NZ,RATE1
POP HL ;Clear stack
RET
RATE1: AND 0FH ;Strip ASCII
LD (SPEED),A
RET
GOVERN: ;3 Speed delay loops (0, 4K & 8K loops)
PUSH BC
LD BC,0
LD A,(SPEED)
DEC A
JP Z,ADJ2
LD B,16
DEC A
JP Z,ADJ1
LD B,64
ADJ1: DEC BC
LD A,B
OR C
JP NZ,ADJ1
ADJ2: POP BC
RET
;
RNDSTART:DW 0 ;Starting entry to maze
HERE: DW 0 ;Location of current cell
;
BKTRK: ;Backtrack to an accessible cell
LD DE,LOTTO ;Array of legal backtracks
LD B,0 ;Count " "
LD HL,(HERE)
LD A,(HL)
AND 2 ;North = 2
JP Z,BKT1
INC B
LD A,1
LD (DE),A ;Store 1=north
INC DE
BKT1: LD A,(HL)
AND 4 ;East=4
JP Z,BKT2
INC B
LD A,2
LD (DE),A ;Store 2=east
INC DE
BKT2: LD A,(HL)
AND 8 ;South=8
JP Z,BKT3
INC B
LD A,3
LD (DE),A
INC DE
BKT3: LD A,(HL)
AND 16 ;West=16
JP Z,BKALL
INC B
LD A,4
LD (DE),A ;Store 4=west
BKALL: LD A,B ;Legal backtrack count
OR A
RET Z ;If no legal backtrack, all cells have
;been visited
INC (HL) ;Set Lo bit to prevent more backtracks
LD (LAST),HL ;Current cell will be superrceded
LD A,(HL)
RRA
OR MGRAPH ;Mask for non-dot graphic
LD DE,OFFSET
ADD HL,DE
LD (HL),A ;Remove dot from cell on screen
LD HL,LOTTO-1
BKA1: INC HL ;Can new cell accept backtrack (i.e.Lo bit reset)
PUSH HL
DEC (HL) ;1=north
JP Z,BKN
DEC (HL) ;2=east
JP Z,BKE
DEC (HL) ;3=south
JP Z,BKS
JP BKW ;Only west left
BKN: LD HL,(HERE)
LD DE,-80
ADD HL,DE ;Goto north cell
LD A,(HL)
AND 1 ;Entry illegal if Lo bit set
JP BKTX ;Zero flag set it so
BKE: LD HL,(HERE)
INC HL ;visit east cell
LD A,(HL)
AND 1
JP BKTX
BKS: LD HL,(HERE)
LD DE,80
ADD HL,DE ;Visit south cell
LD A,(HL)
AND 1
JP BKTX
BKW: LD HL,(HERE)
DEC HL ;Visit west cell
LD A,(HL)
AND 1
JP BKTX
BKTX: JP NZ,BKTX1;Zero flag set if move not legal, try again
LD (HERE),HL ;Record new cell
POP HL ;Clear stack
JP MOVE ;Try another move
BKTX1: POP HL ;Recover array pointer
DEC B
JP NZ,BKA1 ;Try again if more left
JP BKALL ;Else head for exit
;
CHOOSE: ;Choose between Play, Auto escape & exit
LD A,BEL
CALL PUTCH
CALL RNDCELL ;Randomly select a cell to start from
LD DE,SCREEN ;Display inverse text on top line of screen
CALL HILITE
DB 'Choose from 1=Play, 2=Auto escape, 3=Exit ',0
CALL DIRIN ;Get direct input
CP '1'
JP Z,PLAY
CP '2'
JP Z,AUTO
AND 0FH
CP 3
RET ;If 3 or ^C, return with zero set
;
RNDCELL: ;Select a cell at random
LD A,(WIDTH)
DEC A
CALL RAND ;=RND(WIDTH-1)+1
LD E,A
LD D,0 ;Put it in DE
LD HL,(CORNER)
ADD HL,DE ;Move along top line
LD A,(HEIGHT)
DEC A
PUSH HL
CALL RAND ;=RND(HEIGHT-1)+1
POP HL
LD B,A ;Use it as a counterA
LD DE,80
RCL1: ADD HL,DE ;Line feed down
DJNZ RCL1
LD (HERE),HL ;Store the location
LD (RCELL),HL ;twice
LD DE,OFFSET
ADD HL,DE
LD (HL),'*' ;Display cell on screen
LD (LASTSCR),HL ;Store screen location
LD (HERESCR),HL
LD (FSTSCR),HL
RET
RCELL: DW 0 ;Location of randomly selected cell
FSTSCR DW 0 ;Location of above on screen
;
PLAY: LD DE,SCREEN ;Display inverse text
CALL HILITE ; on top line of screen
DB 'North=(N or 3), South=S, East=E, West=W, '
DB '^C=Abort',0
PLAY1: LD HL,(FSTSCR)
LD (HL),'*'
LD HL,(HERESCR)
LD (LASTSCR),HL
CALL BLIP ;Blink cursor, get user input
PUSH AF
LD HL,LASTLN ;Erase bottom line of screen
CALL DELINE
POP AF ;Recover input
CP CTRLC
RET Z ;Exit on ^C
LD HL,(HERE) ;Get current cell
LD (LAST),HL ;It will be superceded
CP '3' ;North?
JP Z,PLN
AND 95 ;Make upper case
CP 'N'
JP Z,PLN
CP 'E'
JP Z,PLE
CP 'S'
JP Z,PLS
CP 'W'
JP Z,PLW
ILLEG: LD A,BEL
CALL PUTCH
LD DE,LASTLN
CALL HILITE
DB 'ILLEGAL MOVE',0
JP PLAY1 ;Try again
PLN: LD A,(HL) ;Get cell data
AND 2 ;2=north
JP Z,ILLEG ;Illegal if not north
LD DE,-80 ;Else enter offset to north cell
JP PLAYX ;& update maze
PLE: LD A,(HL)
AND 4 ;East
JP Z,ILLEG
LD DE,1
JP PLAYX
PLS: LD A,(HL)
AND 8 ;South
JP Z,ILLEG
LD DE,80
JP PLAYX
PLW: LD A,(HL)
AND 16 ;West
JP Z,ILLEG
LD DE,-1
PLAYX: ADD HL,DE ;Move to new location
LD (HERE),HL ;& store it
LD DE,OFFSET
ADD HL,DE
LD (HERESCR),HL ;Store screen location
LD A,(HL) ;Get screen graphic
CP '*' ;If '*' we are backtracking
CALL Z,PLAYBK ;Remove dot from last cell
JP Z,PLAY1 ;And try again
AND 16 ;Same if current cell is dot graphic
CALL NZ,PLAYBK
LD DE,(RNDSTART) ;Get exit location
LD HL,(LAST) ;Compare to previous
CALL CPHLDE
JP NZ,PLAY1 ;If NE try another move
LD HL,SCREEN ;If equal we are finished
CALL DELINE ;Delete top line of screen
LD DE,SCREEN
CALL HILITE
DB 'CONGRATULATIONS **** Try again Y/N ?',0
CALL DIRIN
AND 95
CP 'N'
RET Z
LD HL,(HERESCR) ;Remove '*' marker
LD (HL),' '
LD HL,SCREEN
CALL DELINE
LD DE,SCREEN
CALL HILITE
DB 'Do you want 1. Same Maze, 2. New Maze',0
CALL DIRIN
CP '1'
RET NZ
LD HL,SCREEN ;Clear dots from maze
LD BC,1840
AGIN: LD A,(HL)
AND 0EFH ;Mask out the dot
LD (HL),A
INC HL
DEC BC
LD A,B
OR C
JP NZ,AGIN
LD HL,(RCELL) ;Recover starting cell
LD (HERE),HL
LD DE,OFFSET ;& mark it on screen
ADD HL,DE
LD (HL),'*'
LD (HERESCR),HL ;Store screen location of start
JP PLAY ;Play the maze
BLIP: ;Blink screen, await user input
LD HL,(HERESCR)
LD A,(HL)
LD B,0
CP '*'
JP NZ,BLIP1
CALL DIRIN
RET
BLIP1: OR DOT
LD C,A
AND 8FH ;Mask out Dot bit
LD (HL),A
BLIP2: CALL BLIPIN
JP NZ,BLIPX
DJNZ BLIP2
LD (HL),C
LD B,0
BLIP3: CALL BLIPIN
JP NZ,BLIPX
DJNZ BLIP3
LD B,0
JP BLIP
BLIPX: LD (HL),C
RET
BLIPIN: LD A,DIRIO
LD DE,0FFH
CALL HLBDOS
OR A
RET
;
PLAYBK: PUSH HL
PUSH AF
LD HL,(LASTSCR)
LD A,(HL)
AND 8FH
LD (HL),A
POP AF
POP HL
RET
LASTSCR: DW 0 ;Screen pos'n of last cell
HERESCR: DW 0 ; " " " current cell
;
AUTO: CALL ARATE ;Get input - delay time
LD A,4
CALL RAND ;Select starting direction
LD (DIRECT),A
LD C,4 ;Count of neighbouring cells
LD HL,(HERE)
LD (LAST),HL
DEC (HL) ;Lo bit reset means visited cell
AUT1: CALL GOVERN ;Delay loop
LD A,STATUS
CALL HLBDOS ;Scan for keystroke
OR A
RET NZ ;Exit on any key
LD HL,(FSTSCR)
LD (HL),'*' ;Refresh start display
LD HL,(LAST) ;Compare last cell with exit cell
LD DE,(RNDSTART)
CALL CPHLDE
JP NZ,AUT1A
LD A,BEL ;If equal, we have escaped
CALL PUTCH
LD DE,LASTLN
CALL HILITE
DB 'Round again? Y/N',0
CALL DIRIN
AND 95
CP 'N'
RET
AUT1A: LD HL,(HERE) ;Put graphic on screen
LD (LAST),HL ;Record cell being exited
LD A,(HL) ;Get cell data
RRA ;Get rid of Lo bit
AND 0FH
OR DOT ;Mask with graphic offset
LD DE,OFFSET
ADD HL,DE ;Get screen location
LD (LASTSCR),HL ;Save it
LD (HL),A ;& put a dot at screen location
AUT2: LD A,(DIRECT) ;Get directio¢
LD B,A
LD HL,(HERE)
LD A,(HL) ;Get current cell data
DEC B
JP Z,AUTN ;1=north
DEC B
JP Z,AUTE ;2=east
DEC B
JP Z,AUTS ;3=south
JP AUTW ;only west left
AUTN: LD DE,-80 ;Displacement to north cell
AND 2 ;2=north
JP Z,AUTX
ADD HL,DE ;Visit north
LD A,(HL) ;Get new cell data
AND 1 ;1=entry permitted
JP AUTX
AUTE: AND 4 ;4=east
JP Z,AUTX
INC HL ;Visit east
LD A,(HL)
AND 1
JP AUTX
AUTS: AND 8 ;8=south
JP Z,AUTX
LD DE,80
ADD HL,DE ;Visit south
LD A,(HL)
AND 1
JP AUTX
AUTW: AND 16 ;16=west
JP Z,AUTX
DEC HL ;Visit west
LD A,(HL)
AND 1
AUTX: ;Zero flag has been reset if it's OK to move
LD A,(DIRECT)
JP NZ,OK ;Complete move if OK
DEC C ;Else DEC cell count
JP Z,AUTBAK ;Backtrack if all cells tried
DEC A ;Turn left (after failure)
JP NZ,ATX2 ;Direction must be >0
ADD A,4
ATX2: LD (DIRECT),A
JP AUT1 ;& try new direction
OK: LD (HERE),HL
LD C,4 ;Restore cell count
INC A ;Turn right (after success)
CP 5 ;Direction must be <5
JP C,ATX3
SUB 4
ATX3: LD (DIRECT),A
LD (HERE),HL
DEC (HL) ;Lo bit was 1, now make it zero (no entry)
JP AUT1 ;Try another move
AUTBAK: INC A ;Turn right (to restore original direct)
CP 5
JP C,ATB1
SUB 4
ATB1: LD (DIRECT),A
LD HL,(HERE)
DEC A
JP Z,ATBN ;1=North
DEC A
JP Z,ATBE ;2=South
DEC A
JP Z,ATBS ;3=North
JP ATBW ;Only west left
ATBN: LD A,(HL) ;Get cell data
LD DE,-80 ;Displacement to north cell
AND 2 ;2=north
JP Z,ATBX
ADD HL,DE ;Visit north
LD A,(HL) ;Get new cell data
AND 128 ;Hi bit set means no backtrack
SUB 128 ;Set zero flag if so
JP ATBX
ATBE: LD A,(HL)
AND 4 ;4=east
JP Z,ATBX
INC HL ;Visit east cell
LD A,(HL)
AND 128
SUB 128
JP ATBX
ATBS: LD A,(HL)
AND 8 ;8=south
JP Z,ATBX
LD DE,80
ADD HL,DE ;Visit south
LD A,(HL)
AND 128
SUB 128
JP ATBX
ATBW: LD A,(HL)
AND 16 ;16=west
JP Z,ATBX
DEC HL ;Visit west
LD A,(HL)
AND 128
SUB 128
ATBX: JP NZ,ATOK ;If OK, complete backtrack
LD A,(DIRECT)
DEC A ;Turn left (after failure)
JP NZ,ATBX1
ADD A,4
ATBX1: JP ATB1 ;& try again
ATOK: LD C,4 ;Restore cell count
LD (HERE),HL ;This completes the move
LD HL,(LAST)
LD A,(HL) ;Get data for previous cell
OR 128 ;Set Hi bit to prevent backtrack
LD (HL),A ;Store it
RRA ;Get rid of Lo bit
AND 0FH
OR MGRAPH ;Mask for graphic display (no dot)
LD HL,(LASTSCR)
LD (HL),A ;Remove dot from screen
LD A,(DIRECT)
INC A ;Turn right (after success)
CP 5
JP C,ATOK1
SUB 4
ATOK1: LD (DIRECT),A
JP AUT1 ;& try another move
;
DIRECT: DB 0
ARATE: ;Get user's choice of speed
LD HL,SCREEN ;Erase top line of screen
CALL DELINE
LD DE,SCREEN
CALL HILITE
DB 'Enter speed ... 1=Fast, 2=Medium, 3=Slow',0
CALL DIRIN
AND 0FH
LD (SPEED),A
LD HL,SCREEN ;Erase the message
CALL DELINE
RET
;
PRESS: ;Get a keystroke, at the same time build a random seed
PUSH HL
PUSH DE
PUSH BC
CALL PRINT
DB CR,LF,'Press any key ',0
LD HL,0
PRS1: INC HL
LD C,DIRIO
LD DE,0FFH
CALL BDOS
OR A
JP Z,PRS1
LD (RANDY),HL
POP BC
POP DE
POP HL
RET
RANDY: DW 0 ;Random seed
;
RAND: ;***** Get a random number (Mod A)
PUSH AF
LD HL,(RANDY)
LD A,L
AND 0F0H
LD L,A ;Get Hi nybble of L
LD A,H
AND 0FH
ADD A,L ;Add Lo nybble of H
LD C,A ;Multiply A
LD A,R ;by contents of refresh register
LD B,A
LD H,0
XOR A
RND1: ADD A,B
JR NC,RND2
INC H
RND2: DEC C
JR NZ,RND1
LD L,A
LD (RANDY),HL ;Use result as next seed
LD A,H
POP BC ;Get modulo in B
RND3: SUB B ;& divide
JR NC,RND3
ADD A,L
RND4: SUB B
JR NC,RND4
ADD A,B
INC A ;Return RND(A)+1
RET
;
HLBDOS:; BDOS call saving register pairs
PUSH HL
PUSH DE
PUSH BC
LD C,A ;Receives BDOS function if A
CALL BDOS
POP BC
POP DE
POP HL
RET
;
PUTCH: ; Output char in A to console
PUSH BC
PUSH DE
PUSH HL
PUSH AF
LD E,A
LD C,2
CALL BDOS
POP AF
POP HL
POP DE
POP BC
RET
;
PUTS: ; Output string pointed to by HL to console
LD A,(HL)
OR A
RET Z
CALL PUTCH
INC HL
JP PUTS
RET
;
DIRIN: ;Wait for direct input
PUSH DE
PUSH BC
DIN1: LD A,DIRIO
LD DE,0FFH
CALL HLBDOS
OR A
JP Z,DIN1
POP BC
POP DE
RET
;
PRINT: ;Output a string pointed to by contents of top of stack
; delimited by zero, to console.
EX (SP),HL ;Put pointer to string in HL
XOR A ;Clear register & flags
ADD A,(HL) ;Put char in A set/reset Z flag
INC HL ;Point to next char (or return addr
;if current char a zero)
EX (SP),HL ;and save itè RET Z ;Return on delimiter (zero)
CALL PUTCH ;Display char
JP PRINT ;and get another char.
;
HILITE: ;Output a highlighted string to screen area -> by DE
EX (SP),HL ;Put pointer to string in HL
XOR A ;Clear register & flags
ADD A,(HL) ;Put char in A set/reset Z flag
INC HL ;Point to next char (or return addr
;if current char a zero)
EX (SP),HL ;and save itè RET Z ;Return on delimiter (zero)
OR 128 ;Set Hilite bit
LD (DE),A ;and display char
INC DE
JP HILITE ;and get another char.
;
DELINE: ;Delete line -> by HL
LD D,H
LD E,L
INC DE
LD (HL),' '
LD BC,80
LDIR
RET
;
GETSTR: ; Input console message into buffer
PUSH BC
PUSH HL
PUSH DE
LD HL,TBUF+1 ;Clear char counter
LD (HL),0
DEC HL ;Set maximum line length
LD (HL),80 ;in first byte of buffer
EX DE,HL ;Switch to DE for BDOS Call
LD A,LINEIN
CALL HLBDOS ;Call BDOS line input function
LD HL,TBUF+1 ;Get char count
LD E,(HL) ;into LSB of DE
LD A,(HL) ;and into A for return data
LD D,0 ;and zero MSB
ADD HL,DE ;Add length to start
INC HL ;plus 1 points to end
LD (HL),0 ;Insert zero as delimiter
POP HL
POP DE
POP BC
RET
;
SETDMA: ; -> DE points to transient buffer
LD A,26
CALL HLBDOS
RET
;
CPHLDE: ;Compare HL & DE registers
PUSH HL
PUSH DE
OR A
SBC HL,DE
POP DE
POP HL
RET
;
TWOCR: CALL CRLF ;Execute <CR> & <LF> twice
CRLF: PUSH AF
LD A,CR
CALL PUTCH ;Execute <CR>
LD A,0AH
CALL PUTCH ;Execute <LF>
POP AF
RET
;
LASTBUF: DB 0 ;Mark last byte of program
END