AppleIIAsm-Collection/source/disk18_demos_utils/T.MAKEMAZE
nathanriggs c8cac53c5e Rev 0.4 updates
Massive updates that changes the way most subroutines are handled. Major bugfixes, various utilities added, started higher-level libraries.
2019-04-26 18:49:10 -04:00

600 lines
16 KiB
Plaintext

********************************
* *
* PERFECT MAZE GENERATOR *
* *
********************************
*
** ASSEMBLER DIRECTIVES
*
CYC AVE
EXP ONLY ; TURN OFF LATER
DSK MAKEMAZE
TR ON
OBJ $BFE0
ORG $6000
*
PUT VARS.REQUIRED
USE MIN.MAC.REQUIRED
USE MIN.MAC.ARRAYS
USE MIN.MAC.MATH
USE MIN.MAC.STDIO
PUT MIN.HOOKS.REQUIRED
PUT HOOKS.STDIO
PUT HOOKS.MATH
PUT HOOKS.ARRAYS
*
********************************
* *
* CONSTANT DECLARATIONS *
* *
********************************
*
XLEN KBD "ENTER MAZE SIZE"
XNUM EQU 2*XLEN
BAS EQU $2000 ; BASE ADDRESS FOR ARRAYS
YLEN EQU XLEN ; CURRENT ALGO ONLY DOES SQUARE
XMAX EQU XLEN+1 ; ADD EXTRA COLUMN
YMAX EQU YLEN+1 ; ADD EXTRA ROW
ASZ EQU XMAX*YMAX+10 ; ARRAY SIZE+INFO BYTES
XSTAKS EQU ASZ*2+1 ; COLUMN STACK SIZE; X * Y + 1
YSTAKS EQU ASZ*2+1 ; ROW STACK SIZE; X * Y + 1
*
SOUTHW EQU BAS ; SOUTH WALLS ARRAY
WESTW EQU ASZ+BAS ; WEST WALLS ARRAY
VISITED EQU 2*ASZ+BAS ; CELLS VISITED
XSTACK EQU 3*ASZ+BAS ; STACK FOR COLUMNS
YSTACK EQU 3*ASZ+BAS+XSTAKS ; STACK FOR ROWS
*
********************************
* *
* MAIN PROGRAM LOOP *
* *
********************************
*
INIT
*
JSR HOME
PRN "INITIALIZING...",8D
*
JSR :SETVARS
JSR :OUTWALLS
*
** GET RANDOM STARTING POINT
*
RNDB #2;#<XLEN ; RANDOM STARTING POINT
STA XX ; BETWEEN 2 AND XLEN LOBYTE
RNDB #2;#<YLEN ; RANDOM STARTING POINT
STA YY ; BETWEEN 2 AND YLEN LOBYTE
LDA #>XLEN ; IF XLEN HIBYTE IS 0,
CMP #0 ; THEN SKIP SETTING XX HIBYTE
BEQ :SKIPHI
LDA #>YLEN ; IF YLEN HIBYTE IS 0,
CMP #0 ; THEN SKIP SETTING YY HIBYTE
BEQ :SKIPHI
RNDB #1;#>XLEN ; RANDOMLY SET XX HIBYTE
STA XX+1
RNDB #1;#>YLEN ; RANDOMLY SET YY HIBYTE
STA YY+1
JMP BUILD
:SKIPHI ; JUST SET HIBYTES TO 0
LDA #0
STA XX+1
STA YY+1
*
JMP BUILD
*
********************************
*
:SETVARS
*
** DIM ARRAYS AND FILL
*
DIM162 SOUTHW;#XMAX;#YMAX;#1;#1
DIM162 WESTW;#XMAX;#YMAX;#1;#1
DIM162 VISITED;#XMAX;#YMAX;#1;#0
DIM161 XSTACK;#XSTAKS;#2;#0
DIM161 YSTACK;#YSTAKS;#2;#0
*
** NOW ASSIGN VARIABLE VALUES
*
LDA #0
STA SPTR ; INIT STACK POINTER
STA V0
LDA #1
STA V1
RTS
*
********************************
*
:OUTWALLS
*
** MAKE COLUMN MIN AND MAX TO BE ALL
** WALL (CODE: 1).
*
LDA #0 ; CLEAR ALL TO 0 FIRST
STA XX
STA YY
STA XX+1
STA YY+1
JMP :COLCONT ; SKIP FIRST INCREMENT
*
:COLEDGE
LDA XX
CLC
ADC #1
STA XX
BCC :COLCONT ; IF CARRY SET, THEN INC HIBYTE
INC XX+1
:COLCONT
PUT162 V1;VISITED;XX;#0
PUT162 V1;VISITED;XX;#YMAX-1
LDA XX
CMP #<XMAX-1 ; IF XX LO < MAX SIZE, REPEAT
BNE :COLEDGE
LDA XX+1 ; TEST HI BIT
CMP #>XMAX ; IF XX HI < MAX HI, REPEAT
BNE :COLEDGE
*
** MAKE MIN AND MAX ROWS TO BE ALL WALL
*
JMP :ROWCONT ; SKIP FIRST INCREMENT
*
:ROWEDGE
LDA YY
CLC
ADC #1
STA YY
BCC :ROWCONT ; IF CARRY SET, INC HIBYTE
INC YY+1
:ROWCONT
PUT162 V1;VISITED;#0;YY
PUT162 V1;VISITED;#XMAX-1;YY
LDA YY
CMP #<YMAX-1 ; IF YY LO < YMAX LO, REPEAT
BNE :ROWEDGE
LDA YY+1
CMP #>YMAX ; IF YY HI < YMAX HI, REPEAT
BNE :ROWEDGE
RTS
*
********************************
* *
* BUILD THE MAZE *
* *
********************************
*
BUILD
*
PRN "BUILDING MAZE...",8D8D
JMP CONTSPTR ; SKIP FIRST INC
*
********************************
*
STAKPUSH
*
LDA SPTR ; INCREMENT STACK POINTER
CLC
ADC #1
STA SPTR
BCC CONTSPTR ; IF CARRY SET, INC POINTER HI
INC SPTR+1
CONTSPTR
PUT161 XX;XSTACK;SPTR ; PUT COL ON STACK
PUT161 YY;YSTACK;SPTR ; PUT ROW ON STACK
PUT162 V1;VISITED;XX;YY ; MARK BLOCK AS VISITED
*
********************************
*
CHECKALL
*
** CHECKS ALL ADJACENT BLOCKS FOR A WALL. IF
** COMPLETELY SURROUNDED, POP THE STACK AND
** AND START OVER UNTIL.
*
LDA YY+1 ; COPY HI BYTES OF XX,YY FIRST
STA YP1+1
STA YM1+1
LDA XX+1
STA XP1+1
STA XM1+1
*
LDA YY ; CALC AND STORE YY+1
CLC
ADC #1
STA YP1
BCC :YP1CNT ; IF CARRY SET, INC YYP1 HI
INC YP1+1
:YP1CNT
LDA XX ; CALC AND STORE XX+1
CLC
ADC #1
STA XP1
BCC :XP1CNT ; IF CARRY SET, INC XP1 HI
INC XP1+1
:XP1CNT
LDA YY ; CALC AND STORE YY-1
SEC
SBC #1
STA YM1
BCS :YM1CNT ; IF CARRY CLEAR, DEC YM1 HI
DEC YM1+1
:YM1CNT
LDA XX ; CALC AND STORE XX-1
SEC
SBC #1
STA XM1
BCS :XM1CNT ; IF CARRY CLEAR, DEC XM1 HI
DEC XM1+1
:XM1CNT
*JSR CELLPOS
*
** NOW CHECK ADJACENT CELLS FOR WALLS
*
:IF1 ; IF VISITED(XX,YY+1) = 1
LDA YY+1 ; IF YY HI BYTE = YMAX HI BYTE,
CMP #>YMAX ; THEN TEST YY LOW BYTE
BNE :IF1TEST
LDA YY
CMP #<YMAX ; IF YY LOBYTE = YMAX LOBYTE, THEN
BEQ :IF2 ; AUTOMATICALLY ASSUME ITS A WALL
*
:IF1TEST
GET162 VISITED;XX;YP1
LDA RETURN
CMP #1
BEQ :IF2 ; IF CELL BELOW IS A WALL
; CONTINUE TESTING OTHER
; ADJACENT CELLS
JMP DOMOVE ; OTHERWISE, EXIT CONDITIONAL
*
:IF2 ; IF VISITED(X+1,Y) = 1
*
LDA XX+1 ; IF XX HI BYTE = XMAX HIBYTE
CMP #>XMAX ; THEN TEST LOBYTE
BNE :IF2TEST
LDA XX ; IF XX LOBYTE = XMAX LOBYTE
CMP #<XMAX-1 ; THEN ASSUME RIGHT CELL = WALL
BEQ :IF3
:IF2TEST
GET162 VISITED;XP1;YY ; IF CELL TO RIGHT
LDA RETURN ; IS A WALL, THEN
CMP #1 ; CONTINUE CELL TESTING;
BEQ :IF3 ; ELSE, REPEAT MOVE
JMP DOMOVE
*
:IF3 ; IF VISITED(XX,YY-1) = 1
LDA YY+1 ; IF YY HIBYTE = 0 THEN TEST
CMP #0 ; LOBYTE
BNE :IF3TEST
LDA YY ; IF YY LOBYTE = 0 THEN
CMP #0 ; ASSUME UPPER CELL = WALL
BEQ :IF4 ; AND CONTINUE TESTING
:IF3TEST
GET162 VISITED;XX;YM1
LDA RETURN ; IF CELL ABOVE IS WALL THEN
CMP #1 ; CONTINUE TESTING CELLS;
BEQ :IF4 ; ELSE, REPEAT MOVE
JMP DOMOVE
*
:IF4 ; IF VISITED(XX-1,YY) = 1
LDA XX+1 ; IF XX HIBYTE = 0
CMP #0 ; THEN TEST LOBYTES
BNE :IF4TEST
LDA XX ; IF XX LOBYTE = 0
CMP #0 ; THEN ASSUME LEFT CELL = WALL
BEQ :POP ; AND POP THE STACK
:IF4TEST
GET162 VISITED;XM1;YY
LDA RETURN ; IF LEFT CELL = 1
CMP #1 ; THEN ALL ADJACENT CELLS ARE WALLS
BEQ :POP ; SO POP THE STACK
*
JMP DOMOVE ; OTHERWISE, REPEAT MOVING
*
********************************
*
:POP
*
GET161 XSTACK;SPTR ; GET NEW XX POSITION
LDA RETURN
STA XX ; STORE LO BYTE
LDA RETURN+1
STA XX+1 ; STORE HI BYTE
GET161 YSTACK;SPTR
LDA RETURN ; GET NEW Y POSITION
STA YY
LDA RETURN+1
STA YY+1
LDA SPTR ; POP STACK
SEC
SBC #1
STA SPTR
BCS :SPCNT2 ; IF CARRY NOT SET, DEC HIBYTE
DEC SPTR+1
:SPCNT2
LDA SPTR+1 ; IF POINTER HIBYTE > 0
CMP #0 ; THEN REPEAT MOVEMENT
BNE :DOREPEAT
LDA SPTR ; OTHERWISE, TEST LOBYTE
CMP #1 ; IF STILL MORE ON STACK
BEQ :DOREPEAT
BCS :DOREPEAT ; THEN REPEAT MOVEMENT
JMP DISPMAZE ; OTHERWISE, FINISHED!
*
:DOREPEAT
JMP CHECKALL
*
********************************
*
DOMOVE
*
** MOVE IN A RANDOM DIRECTION
*
JSR RAND8
CMP #64 ; IF RND < 64
BCC :MVDJ
CMP #128 ; ELSE IF RND < 128
BCC :MVRJ
CMP #192 ; ELSE IF RND < 192
BCC :MVUPJ
JMP :MVLEFT ; ELSE RND IS > 191
:MVUPJ JMP :MVUP
:MVRJ JMP :MVRIGHT
:MVDJ JMP :MVDOWN
*
:MVDOWN
LDA YY+1 ; IF YY HIBYTE = YMAX HIBYTE
CMP #>YMAX ; THEN TEST LOBYTES
BNE :DTEST ; OTHERWISE, TEST CELL BELOW
LDA YY
CMP #<YMAX ; IF YY LOBYTE = YMAX LOBYTE
BEQ :DNO ; THEN ASSUME CELL BELOW = WALL
:DTEST
GET162 VISITED;XX;YP1
LDA RETURN
CMP #0 ; IF CELL BELOW NOT A WALL
BEQ :DOWNGO ; THEN MOVE DOWN
:DNO
JMP DOMOVE ; ELSE, TRY MOVING ELSEWHERE
:DOWNGO
PUT162 V0;SOUTHW;XX;YY ; PUT 0 AT CURRENT POSITION
LDA YP1 ; INCREASE YY POSITION (MOVE DOWN)
STA YY
LDA YP1+1
STA YY+1
:DOWNC
JMP STAKPUSH ; PUSH POSITION TO STACK, REPEAT
*
:MVRIGHT
LDA XX+1 ; IF XX HIBYTE = XMAX HIBYTE
CMP #>XMAX ; THEN TEST LOW BYTE
BNE :RTEST ; ELSE CONTINUE CELL CHECK
LDA XX
CMP #<XMAX-1 ; IF XX LOBYTE = XMAX LOBYTE
BEQ :RNO ; THEN ASSUME WALL TO RIGHT
; AND SKIP THE CHECK
:RTEST
GET162 VISITED;XP1;YY
LDA RETURN ; IF CELL TO RIGHT IS NOT WALL
CMP #0 ; THEN MOVE THERE
BEQ :RIGHTGO
:RNO
JMP DOMOVE ; OTHERWISE, TRY MOVING ELSEWHERE
:RIGHTGO
PUT162 V0;WESTW;XP1;YY ; MARK RIGHT CELL AS EMPTY
LDA XP1 ; MOVE TO RIGHT CELL
STA XX
LDA XP1+1
STA XX+1
:RIGHTC
JMP STAKPUSH
*
:MVUP
LDA YY+1 ; IF YY HIBYTE != 0 THEN
CMP #0 ; SKIP LOBYTE TEST
BNE :UTEST
LDA YY ; IF YY LOBYTE = 0 THEN
CMP #0 ; ASSUME UP CELL IS WALL
BEQ :UNO ; AND MOVE ELSEWHERE
:UTEST
GET162 VISITED;XX;YM1
LDA RETURN ; IF VISITED(XX,YY) = 0
CMP #0 ; (NO WALL) THEN
BEQ :UPGO ; MOVE ON UP THERE
:UNO
JMP DOMOVE
:UPGO
PUT162 V0;SOUTHW;XX;YM1
LDA YM1 ; MOVE UP ONE CELL
STA YY
LDA YM1+1
STA YY+1
:UPC
JMP STAKPUSH
*
:MVLEFT
LDA XX+1 ; IF XX HIBYTE != 0 THEN
CMP #0 ; SKIP LOBYTE TEST
BNE :LTEST
LDA XX ; IF XX LOBYTE = 0
CMP #0 ; THEN ASSME LEFT CELL IS WALL
BEQ :LNO ; AND TRY TO MOVE ELSEWHERE
:LTEST
GET162 VISITED;XM1;YY
LDA RETURN ; IF LEFT CELL IS NOT A WALL
CMP #0 ; THEN LET'S MOVE THERE
BEQ :LEFTGO
:LNO
JMP DOMOVE
:LEFTGO
PUT162 V0;WESTW;XX;YY
LDA XM1 ; MOVE ONE CELL LEFT
STA XX
LDA XM1+1
STA XX+1
:LEFTC
JMP STAKPUSH
*
********************************
* *
* DISPLAY THE MAZE *
* *
********************************
*
DISPMAZE
*
** SEND MAZE TO DISPLAY OUTPUT, FORMATTED
*
PRN "PRINTING...",8D8D
LDA #0
STA XX
:XLOOP ; PRINT FIRST LINE OF WALLS
INC XX
PRN "X"
LDA XX
CMP #XNUM-1
BNE :XLOOP
PRN " ",8D
*
LDA #0 ; RESET XX,YY
STA XX+1
STA YY+1
LDA #1
STA XX
STA YY
WLP
*
** IF WESTW(X,Y) == 0
*
GET162 WESTW;XX;YY
LDA RETURN
CMP #0
BEQ NOWALLW ; THEN PRINT ...
YESWALLW ; ELSE PRINT X..
PRN "X "
JMP CONTWLP
NOWALLW
PRN " "
*
CONTWLP
LDA XX ; INCREASE XX
CLC
ADC #1 ; LOBYTE FIRST
STA XX
BCC :SKIPHI ; IF HI = 0, SKIP INC
INC XX+1
:SKIPHI
LDA XX+1 ; IF HIBYTE != XMAX HI
CMP #>XMAX
BNE WLP ; THEN REPEAT
LDA XX ; OTHERWISE, TEST LOWS
CMP #<XMAX-1 ; IF LOBYTE != XMAX-1
BNE WLP ; REPEAT
*
PRN "X",8D ; OTHERWISE, GO TO NEXT LINE
*
LDA #1 ; RESET XX COUNTER
STA XX
LDA #0
STA XX+1
*
** IF SOUTHW(X,Y) == 0
*
SLP
GET162 SOUTHW;XX;YY
LDA RETURN
CMP #0
BEQ NOSOUTH ; THEN PRINT X..
YSOUTH ; ELSE PRINT XXX
PRN "XX"
JMP CONTSLP
NOSOUTH
PRN "X "
CONTSLP
LDA XX ; INCREASE XX BY 1
CLC
ADC #1
STA XX
BCC :SKIPHI2 ; SKIP HI INC IF NO CARRY
INC XX+1
:SKIPHI2
LDA XX+1 ; TEST HIBYTE OF XX
CMP #>XMAX ; IF HI != XMAX HI
BNE SLP ; REPEAT
LDA XX ; ELSE, TEST LOBYTE
CMP #<XMAX-1 ; IF XX LO != XMAX LO - 1
BNE SLP ; REPEAT
*
PRN "X",8D ; OTHERWISE, NEW LINE
*
LDA #0 ; RESET XX
STA XX+1
LDA #1
STA XX
LDA YY ; INCREASE YY BY 1
CLC
ADC #1
STA YY
BCC :SKIP ; IF NO CARRY, SKIP HI INC
INC YY+1
:SKIP
LDA YY+1 ; IF YY HI != YMAX HI
CMP #>YMAX ; THEN NOT DONE; REPEAT LOOPS
BNE REPT
LDA YY ; ELSE IF YY LO != YMAX LO
CMP #<YMAX-1 ; THEN NOT DONE; REPEAT LOOPS
BEQ DISPEXIT ; OTHERWISE, DONE!
REPT JMP WLP
*
DISPEXIT
*
_WAIT
JMP REENTRY
*
********************************
* *
* VARIABLES *
* *
********************************
*
V0 DS 1 ; USED BECAUSE OF CURRENT
V1 DS 1 ; ARRAY DIM LIMITATIONS
*
XX DS 2 ; CURRENT COLUMN
YY DS 2 ; CURRENT ROW
SPTR DS 2 ; ARRAY STACK POINTER
XP1 DS 2 ; X PLUS ONE
XM1 DS 2 ; X MINUS ONE
YP1 DS 2 ; Y PLUS ONE
YM1 DS 2 ; Y MINUS ONE
*
********************************
* *
* LOW-LEVEL ROUTINES *
* *
********************************
*
PUT MIN.LIB.REQUIRED
*
** INDIVIDUAL SUBROUTINES
*
** ARRAYS
*
PUT MIN.SUB.ADIM161
PUT MIN.SUB.ADIM162
PUT MIN.SUB.AGET161
PUT MIN.SUB.AGET162
PUT MIN.SUB.APUT161
PUT MIN.SUB.APUT162
*
** MATH
*
PUT MIN.SUB.RAND8
PUT MIN.SUB.RANDB
*
** STDIO
*
PUT MIN.SUB.DPRINT
PUT MIN.SUB.XPRINT
*