MAZE Template:
First thing I had to do... create an input template for the Maze. I decided to limit the maze area to the first 22 lines & keep the last two for key instructions (<ESC>=Exit) & basic messages. The program will work on any maze in this format. The assumption is that the maze area is within the proper 24x80 limitations & constrained by walls of X's - there is NO validation of the maze template. This is strictly an exercise of navigating through the maze. The starting point is designated in the template by an * and the end point is the @ symbol. Reaching the end simply produces the message "***WINNER***" without any other action. The little maze runner can continue happily if he likes until the <ESC> key is pressed.
Above: The MAZE template created in Notepad. START circled in YELLOW & the END in RED.
Note - Every line in the MAZE template ends with a $. This standard eliminates the need for a hard-coded $ within the program that is required for the WTO Supervisor Call (SCREEN Routine).
Creating/Running the MAZE Program:
On Friday evening (last night) my wife had to run to an appointment after dinner so, alone for a couple hours, I pulled out my laptop & cranked through some code. It was much easier than I envisioned. The maze runner either moves left or right +/- 1 position - or up & down +/- 80 positions (to account for an entire row). If that resulting spot has an 'X' the move is ignored. If the spot is the address of the @ sign the "Winner" message is displayed. I also drop a breadcrumb (.) at each spot the maze runner guy moves from as well as calculate the X/Y coordinates to display with each move.
Above: The program in action. Breadcrumbs create a trail. Current position circled in GREEN.
It was fun running the program & testing the capabilities. It was also gratifying reaching the end & watching the ***WINNER*** message appear.
Above: Sweet victory as the finish line is reached. *** WINNER ***
The little maze runner guy went down every corridor testing the strength of the walls. He couldn't bust through the walls but got a lot of exercise exploring the nooks & crannies...
Above: Every path & corridor has been traversed & marked with a breadcrumb.
Create ANY MAZE Template:
Multiple mazes can be created with the active one saved as TDMAZE.TXT (don't overlay without a backup after all that tedious work). Here's a minimal maze with the only constraints around the edges. The program works exactly the same. The positions of the start/end points are immaterial - in this example I flipped them starting in the bottom right & ending at the top left.
Above: Maze with Minimum Wall Constraints, Start (YELLOW) and End (RED) points.
A maze without internal walls looks more like a simplistic drawing application (due to the breadcrumb trail). I maneuvered the little maze runner guy to write my name - TONY.
TDMAZE.ALC - Main Processing Logic:
Logic is very simple. Read the text file & load each record into the array named MAZE. Record the occurrence of the start/end symbols (within the PARSE routine). Then move on to the Screen & Key handling. The SCREEN routine displays the 24x80 lines (via WTO SVC Calls) & reads the keystroke when pressed. All keys other than <ESC> & directional arrows are ignored. <ESC> exits the program. The arrows increment/decrement the current "little maze runner guy" position & tests if it's a wall (X). If not the maze runner moves along with his vacated position replaced with a breadcrumb (.).
***********************************************************************
* MAINLINE PROCEDURE *
***********************************************************************
PRINT NOGEN
SVC @TRACE ISSUE SUPERVISOR CALL
DC CL4'IOF ' KEYBOARD INTERRUPT OFF
*
XFILI STDWKI OPEN INPUT FILE
*
LA 9,MAZE LOAD MAIN ADDRESS
GETI EQU *
XREAD IREC,80 READ INPUT RECORD
BNZ EOFI EOF - EXIT ROUTINE
*
BAL 6,PARSE PARSE INPUT RECORD
*
B GETI READ NEXT RECORD
EOFI EQU *
MVI 0(9),X'FF' MARK END OF TABLE
*
MVC MAZEMSG,MAZEMSG1 INIT MAZE MESSAGE
*
MVI VBITS,@BKWT SET BG(BLACK)/FG(WHITE)
BAL 6,VRESET CHANGE SCREEN ATTRIBUTES
LOOP EQU *
BAL 6,SCREEN BUILD SCREEN
*
CLI KEY,@K#ESC KEY = ESCAPE???
BE LOOPX YES - EXIT PLEASE
*
L 3,MAZEPTR LOAD LAST CURSOR
*
CLI KEY,@K#ARWU KEY = ARROW UP???
BE LOOPZU YES - PROCESS KEY
CLI KEY,@K#ARWD KEY = ARROW DOWN???
BE LOOPZD YES - PROCESS KEY
CLI KEY,@K#ARWL KEY = ARROW LEFT???
BE LOOPZL YES - PROCESS KEY
CLI KEY,@K#ARWR KEY = ARROW RIGHT???
BNE LOOP NO - DISPLAY SCREEN
*
* ARROW KEYS
*
LOOPZR EQU *
AH 3,=Y(1) Y INCREMENT POINTER
MVC MAZEKEY,=CL6'RIGHT' TRACK KEY DIRECTION
B LOOPZ1 TEST NEW POSITION
LOOPZL EQU *
SH 3,=Y(1) Y DECREMENT POINTER
MVC MAZEKEY,=CL6'LEFT' TRACK KEY DIRECTION
B LOOPZ1 TEST NEW POSITION
LOOPZD EQU *
AH 3,=Y(80) X INCREMENT POINTER
MVC MAZEKEY,=CL6'DOWN' TRACK KEY DIRECTION
B LOOPZ1 TEST NEW POSITION
LOOPZU EQU *
SH 3,=Y(80) X DECREMENT POINTER
MVC MAZEKEY,=CL6'UP' TRACK KEY DIRECTION
LOOPZ1 EQU *
CLI 0(3),C'X' HITTING A WALL???
BE LOOP YES - IGNORE MOVE
*
L 4,MAZEPTR LOAD CURRENT CURSOR
MVI 0(4),C'.' DROP BREADCRUMB
C 3,MAZEEND MAZE END REACHED?
BE LOOPEND YES - VICTORY!!!
ST 3,MAZEPTR RESET CURRENT CURSOR
MVI 0(3),C'*' MOVE MAZE RUNNER
BAL 6,POSCALC POSITION CALCULATOR
B LOOP DISPLAY SCREEN AGAIN
LOOPEND EQU *
MVC MAZEMSG,MAZEMSG3 WINNER MESSAGE!
B LOOP DISPLAY SCREEN AGAIN
LOOPX EQU *
B RETURN EXIT PROGRAM PLEASE
***********************************************************************
The Position Calculation serves no purpose other than to display the coordinates in a message. Just a nice aesthetic touch to the application... Because of the wall constraints the X/Y calculation is simple - no need to test for a remainder of zero when dividing by 80 - it will never be zero.
***********************************************************************
* POSITION CALCULATION *
***********************************************************************
DC F'0' RETURN ADDRESS SAVE AREA
POSCALC EQU *
ST 6,*-4 SAVE RETURN ADDRESS
*
L 6,MAZEPTR LOAD CURSOR ADDRESS
S 6,=A(MAZE) SUBSTRACT MAZE ADDRESS
CVD 6,DUBB CONVERT TO DECIMAL
DP DUBB,=P'80' DIVIDE BY 80 COLUMNS
ZAP XX,DUBB+4(2) EXTRACT X-COORDINATE
ZAP YY,DUBB+6(2) EXTRACT Y-COORDINATE
*
MVC MAZEMSG,MAZEMSG2 MOVE MAZE MESSAGE 2
UNPK MAZEMSG+5(3),XX UNPACK X-COORDINATE
UNPK MAZEMSG+9(3),YY UNPACK Y-COORDINATE
OI MAZEMSG+7,X'F0' TURN ON ZONE BITS
OI MAZEMSG+11,X'F0' TURN ON ZONE BITS
MVC MAZEMSG+14(6),MAZEKEY MOVE MAZE KEY
POSCALCX EQU *
L 6,POSCALC-4 RESTORE LINK REGISTER
BR 6 BRANCH ON LINK REGISTER
***********************************************************************
This was not an elaborate exercise. Tracking the "little maze runner" & the walls was pretty easy. After the Assembly/Link it worked perfectly on the very first test - the maze guy was flying off the walls! Although, I was very diligent with my proofreading.
TDMAZE.ALC - Full Source Code:
Full source code minus the Copybooks for Screen, Video & Key handling. Also, some commonly used variables & copybooks may appear although they aren't utilized - this makes cloning for other exercises quicker.
TITLE 'TDMAZE - PC/370 4.2 // DELIA'
***********************************************************************
* *
* MODULE: TDMAZE. *
* AUTHOR: TONY DELIA. *
* DATE: 03/06/2020. *
* DESC: PC/370 SIMPLE MAZE ALGORITHM. *
* NOTE: PC/370 RELEASE 4.2 *
* *
***********************************************************************
EJECT
***********************************************************************
* T D M A Z E P R O G R A M *
***********************************************************************
TDMAZE START 0 START PROGRAM
STM 14,12,12(13) SAVE REGISTERS
LR 12,15 LOAD PROGRAM ENTRY POINT
USING TDMAZE+0*4096,12 BASE REGISTER 1
L 11,BASE2 LOAD BASE REGISTER 2
USING TDMAZE+1*4096,11 TELL ASSEMBLER ABOUT BASE2
L 10,BASE3 LOAD BASE REGISTER 3
USING TDMAZE+2*4096,10 TELL ASSEMBLER ABOUT BASE3
ST 13,SAVE+4 SAVE EXTERNAL SAVE ADDRESS
LR 14,13 XFER ADDRESS TO TEMP R14
LA 13,SAVE LOAD INTERNAL SAVE ADDRESS
ST 13,8(14) SAVE IN EXTERNAL SAVE AREA
B GO BRANCH TO PROCESSING RTN
***********************************************************************
RETURN EQU * TIME TO RETURN
L 13,SAVE+4 RESTORE REGISTER 13
LM 14,12,12(13) RESTORE REMAINING REGS
SR 15,15 CLEAR RETURN CODE
BR 14 BRANCH TO CALLING PROGRAM
***********************************************************************
SAVE DC 18F'0' S A V E A R E A
***********************************************************************
BASE2 DC A(TDMAZE+1*4096) BASE2 DISPLACEMENT
BASE3 DC A(TDMAZE+2*4096) BASE3 DISPLACEMENT
***********************************************************************
GO EQU * BEGIN PROCESSING ...
***********************************************************************
EJECT
***********************************************************************
* MAINLINE PROCEDURE *
***********************************************************************
PRINT NOGEN
SVC @TRACE ISSUE SUPERVISOR CALL
DC CL4'IOF ' KEYBOARD INTERRUPT OFF
*
XFILI STDWKI OPEN INPUT FILE
*
LA 9,MAZE LOAD MAIN ADDRESS
GETI EQU *
XREAD IREC,80 READ INPUT RECORD
BNZ EOFI EOF - EXIT ROUTINE
*
BAL 6,PARSE PARSE INPUT RECORD
*
B GETI READ NEXT RECORD
EOFI EQU *
MVI 0(9),X'FF' MARK END OF TABLE
*
MVC MAZEMSG,MAZEMSG1 INIT MAZE MESSAGE
*
MVI VBITS,@BKWT SET BG(BLACK)/FG(WHITE)
BAL 6,VRESET CHANGE SCREEN ATTRIBUTES
LOOP EQU *
BAL 6,SCREEN BUILD SCREEN
*
CLI KEY,@K#ESC KEY = ESCAPE???
BE LOOPX YES - EXIT PLEASE
*
L 3,MAZEPTR LOAD LAST CURSOR
*
CLI KEY,@K#ARWU KEY = ARROW UP???
BE LOOPZU YES - PROCESS KEY
CLI KEY,@K#ARWD KEY = ARROW DOWN???
BE LOOPZD YES - PROCESS KEY
CLI KEY,@K#ARWL KEY = ARROW LEFT???
BE LOOPZL YES - PROCESS KEY
CLI KEY,@K#ARWR KEY = ARROW RIGHT???
BNE LOOP NO - DISPLAY SCREEN
*
* ARROW KEYS
*
LOOPZR EQU *
AH 3,=Y(1) Y INCREMENT POINTER
MVC MAZEKEY,=CL6'RIGHT' TRACK KEY DIRECTION
B LOOPZ1 TEST NEW POSITION
LOOPZL EQU *
SH 3,=Y(1) Y DECREMENT POINTER
MVC MAZEKEY,=CL6'LEFT' TRACK KEY DIRECTION
B LOOPZ1 TEST NEW POSITION
LOOPZD EQU *
AH 3,=Y(80) X INCREMENT POINTER
MVC MAZEKEY,=CL6'DOWN' TRACK KEY DIRECTION
B LOOPZ1 TEST NEW POSITION
LOOPZU EQU *
SH 3,=Y(80) X DECREMENT POINTER
MVC MAZEKEY,=CL6'UP' TRACK KEY DIRECTION
LOOPZ1 EQU *
CLI 0(3),C'X' HITTING A WALL???
BE LOOP YES - IGNORE MOVE
*
L 4,MAZEPTR LOAD CURRENT CURSOR
MVI 0(4),C'.' DROP BREADCRUMB
C 3,MAZEEND MAZE END REACHED?
BE LOOPEND YES - VICTORY!!!
ST 3,MAZEPTR RESET CURRENT CURSOR
MVI 0(3),C'*' MOVE MAZE RUNNER
BAL 6,POSCALC POSITION CALCULATOR
B LOOP DISPLAY SCREEN AGAIN
LOOPEND EQU *
MVC MAZEMSG,MAZEMSG3 WINNER MESSAGE!
B LOOP DISPLAY SCREEN AGAIN
LOOPX EQU *
B RETURN EXIT PROGRAM PLEASE
***********************************************************************
EJECT
***********************************************************************
* PARSE RECORD R9=MAZE *
***********************************************************************
DC F'0' RETURN ADDRESS SAVE AREA
PARSE EQU *
ST 6,*-4 SAVE RETURN ADDRESS
*
CLI 0(9),X'FF' MAZE TABLE FULL??
BE PARSEX YES - EXIT ROUTINE
*
MVC 0(80,9),IREC STORE MAZE DATA
*
LA 7,79 LOAD MAZE COUNT
LR 8,9 LOAD MAZE ADDRESS
*
PARL1A BC 0,PARL1B BYPASS WHEN FOUND
CLI 0(8),C'*' STARTING TOKEN ???
BNE PARL1B NO - CONTINUE PLEASE
ST 8,MAZEBEG YES - STORE ADDRESS
ST 8,MAZEPTR SET MAZE CURSOR
OI PARL1A+1,X'F0' SET BYPASS SWITCH
*
PARL1B BC 0,PARBUMP BYPASS WHEN FOUND
CLI 0(8),C'@' FINISH TOKEN???
BNE PARBUMP NO - CONTINUE PLEASE
ST 8,MAZEEND YES - STORE ADDRESS
OI PARL1B+1,X'F0' SET BYPASS SWITCH
PARBUMP EQU *
LA 8,1(,8) BUMP TABLE POINTER
BCT 7,PARL1A TEST NEXT POSITION
PARGO EQU *
LA 9,80(,9) BUMP TABLE POINTER
PARSEX EQU *
L 6,PARSE-4 RESTORE LINK REGISTER
BR 6 BRANCH ON LINK REGISTER
***********************************************************************
EJECT
***********************************************************************
* POSITION CALCULATION *
***********************************************************************
DC F'0' RETURN ADDRESS SAVE AREA
POSCALC EQU *
ST 6,*-4 SAVE RETURN ADDRESS
*
L 6,MAZEPTR LOAD CURSOR ADDRESS
S 6,=A(MAZE) SUBSTRACT MAZE ADDRESS
CVD 6,DUBB CONVERT TO DECIMAL
DP DUBB,=P'80' DIVIDE BY 80 COLUMNS
ZAP XX,DUBB+4(2) EXTRACT X-COORDINATE
ZAP YY,DUBB+6(2) EXTRACT Y-COORDINATE
*
MVC MAZEMSG,MAZEMSG2 MOVE MAZE MESSAGE 2
UNPK MAZEMSG+5(3),XX UNPACK X-COORDINATE
UNPK MAZEMSG+9(3),YY UNPACK Y-COORDINATE
OI MAZEMSG+7,X'F0' TURN ON ZONE BITS
OI MAZEMSG+11,X'F0' TURN ON ZONE BITS
MVC MAZEMSG+14(6),MAZEKEY MOVE MAZE KEY
POSCALCX EQU *
L 6,POSCALC-4 RESTORE LINK REGISTER
BR 6 BRANCH ON LINK REGISTER
***********************************************************************
EJECT
***********************************************************************
* BUILD SCREEN *
***********************************************************************
DC F'0' RETURN ADDRESS SAVE AREA
SCREEN EQU *
ST 6,*-4 SAVE RETURN ADDRESS
*
LA 5,SCTAB LOAD TABLE ADDRESS
SC1LP EQU *
CLI 0(5),X'FF' END OF TABLE ???
BE SC2LP YES - EXIT LOOP PLEASE
*
MVC VXYS,0(5) MOVE CURSOR POSITION
BAL 6,VXYSET SET CURSOR POSITION
L 2,4(5) LOAD MESSAGE ADDRESS
SVC @WTO ISSUE SUPERVISOR CALL
*
LA 5,8(,5) BUMP TABLE POINTER
B SC1LP TEST NEXT TABLE ENTRY
SC2LP EQU *
*
* ACCEPT KEYSTROKE
*
BAL 6,KBGET READ KEYBOARD INPUT
MVC KEY,KBCHR STORE KEYSTROKE
*
CLI KEY,@K#ESC KEY = ESCAPE ???
BE SCREENX YES - EXIT ROUTINE
*
CLI KEY,@K#ARWU KEY = ARROW UP???
BE SCREENX YES - EXIT ROUTINE
CLI KEY,@K#ARWD KEY = ARROW DOWN???
BE SCREENX YES - EXIT ROUTINE
CLI KEY,@K#ARWL KEY = ARROW LEFT???
BE SCREENX YES - EXIT ROUTINE
CLI KEY,@K#ARWR KEY = ARROW RIGHT???
BNE SC2LP NO - ENTER NEW KEY
SCREENX EQU *
L 6,SCREEN-4 RESTORE LINK REGISTER
BR 6 BRANCH ON LINK REGISTER
***********************************************************************
EJECT
***********************************************************************
* WORKING STORAGE *
***********************************************************************
DUBB DC D'0' DOUBLEWORD
FULL DC F'0' FULLWORD
HALF DC H'0' HALFWORD
XX DC PL2'0' X-POINTER
YY DC PL2'0' Y-POINTER
KEY DC CL1' ' KEY STROKE (@RDKEY)
CHAR DC CL1' ',C'$' KEY CHARACTER
@YES EQU C'Y' YES
@NO EQU C'N' NO
@ESC EQU 27 ESCAPE KEY
@CR EQU 13 CARRIAGE RETURN
@LF EQU 10 LINE FEED
@KEYLO EQU 32 ASCII KEY - LO VALUE
@KEYHI EQU 126 ASCII KEY - HI VALUE
BLOCK DC AL1(219) BLOCK CHARACTER
***********************************************************************
* DATA CONTROL BLOCK SET UP *
***********************************************************************
STDWKI DC CL64'C:\PC370\TDMAZE.TXT'
***********************************************************************
* INPUT RECORD AREA *
***********************************************************************
IREC DC CL80' ' INPUT RECORD
***********************************************************************
LTORG LITERAL POOL
***********************************************************************
* COPYBOOKS *
***********************************************************************
COPY CPY/TDBOX.CPY COPYBOOK - BOX DISPLAY
COPY CPY/TDVID.CPY COPYBOOK - VIDEO UTILITY
COPY CPY/TDKBD.CPY COPYBOOK - KEYBOARD INPUT
COPY CPY/TDKEY.CPY COPYBOOK - KEYSTROKES
COPY CPY/TDCLR.CPY COPYBOOK - COLORS
COPY CPY/TDSVC.CPY COPYBOOK - SUPERVISOR
***********************************************************************
* BOX COMPONENTS (COORDINATES/FRAME) *
***********************************************************************
BXTAB DS 0F
DC AL1(0,0,23,79) BOX COORDINATES/FRAME
***********************************************************************
* SCREEN DISPLAY COMPONENTS *
***********************************************************************
SCTAB DS 0F
DC AL1(0,0,0,0),A(MAZE+80*0) SCREEN COORDINATES/MSG
DC AL1(0,0,1,0),A(MAZE+80*1) SCREEN COORDINATES/MSG
DC AL1(0,0,2,0),A(MAZE+80*2) SCREEN COORDINATES/MSG
DC AL1(0,0,3,0),A(MAZE+80*3) SCREEN COORDINATES/MSG
DC AL1(0,0,4,0),A(MAZE+80*4) SCREEN COORDINATES/MSG
DC AL1(0,0,5,0),A(MAZE+80*5) SCREEN COORDINATES/MSG
DC AL1(0,0,6,0),A(MAZE+80*6) SCREEN COORDINATES/MSG
DC AL1(0,0,7,0),A(MAZE+80*7) SCREEN COORDINATES/MSG
DC AL1(0,0,8,0),A(MAZE+80*8) SCREEN COORDINATES/MSG
DC AL1(0,0,9,0),A(MAZE+80*9) SCREEN COORDINATES/MSG
DC AL1(0,0,10,0),A(MAZE+80*10) SCREEN COORDINATES/MSG
DC AL1(0,0,11,0),A(MAZE+80*11) SCREEN COORDINATES/MSG
DC AL1(0,0,12,0),A(MAZE+80*12) SCREEN COORDINATES/MSG
DC AL1(0,0,13,0),A(MAZE+80*13) SCREEN COORDINATES/MSG
DC AL1(0,0,14,0),A(MAZE+80*14) SCREEN COORDINATES/MSG
DC AL1(0,0,15,0),A(MAZE+80*15) SCREEN COORDINATES/MSG
DC AL1(0,0,16,0),A(MAZE+80*16) SCREEN COORDINATES/MSG
DC AL1(0,0,17,0),A(MAZE+80*17) SCREEN COORDINATES/MSG
DC AL1(0,0,18,0),A(MAZE+80*18) SCREEN COORDINATES/MSG
DC AL1(0,0,19,0),A(MAZE+80*19) SCREEN COORDINATES/MSG
DC AL1(0,0,20,0),A(MAZE+80*20) SCREEN COORDINATES/MSG
DC AL1(0,0,21,0),A(MAZE+80*21) SCREEN COORDINATES/MSG
DC AL1(0,0,22,0),A(MAZE+80*22) SCREEN COORDINATES/MSG
DC AL1(0,0,23,0),A(MAZE+80*23) SCREEN COORDINATES/MSG
DC AL1(0,0,22,36),A(MAZEMSG) SCREEN COORDINATES/MSG
DC XL1'FF' END OF TABLE
***********************************************************************
* MAZE *
***********************************************************************
MAZEKEY DC CL6' ' MAZE MESSAGE KEY
MAZEMSG1 DC CL40'USE ARROW KEYS' MAZE MESSAGE 1
MAZEMSG2 DC CL40'X,Y=(999,999) XXXXXX' MAZE MESSAGE 2
MAZEMSG3 DC CL40'*** WINNER ***' MAZE MESSAGE 3
MAZEMSG DC CL40' ',C'$' MAZE MESSAGE TEXT AREA
MAZEPTR DC A(MAZE) MAZE POINTER - CURSOR
MAZEBEG DC A(MAZE) MAZE POINTER - BEGIN
MAZEEND DC A(MAZE) MAZE POINTER - END
MAZE DC 24CL80' ' 24X80 MAZE TEMPLATE
DC XL1'FF' END OF MAZE TEMPLATE
***********************************************************************
END TDMAZE
Hope someone out there enjoys this fun exercise... now I can focus on yard work again.