PROGRAM MAZE C C MAZE - USES A VT100 TO WANDER AROUND. C THE VT100 MUST HAVE ADVANCED VIDEO OPTION. C ANSI VT100 ESCAPE SEQUENCES ARE USED. C C WRITTEN BY DON MCLEAN C OF THE MACNEAL-SCHWENDLER CORP. C C THE PURPOSE OF THIS PROGRAM WAS TO C 1. LEARN SOMETHING ABOUT THE VT100 GRAPHICS. C 2. KEEP MY KIDS BUSY ON WEEKENDS. WHILE I TRIED C TO GET SOMETHING ELSE DONE. C C USE OF THIS PROGRAM FOR ANY PURPOSE OTHER THAN FUN C IS PROHIBITED. C IMPLICIT INTEGER*4 (A-Z) C C MAZE DIMENSIONS C HMAX AND WMAX SHOULD NOT BE LARGER THAN 22 AND 80 RESP. C PARAMETER HMAX=22, WMAX=132, DMAX=5 C DIMENSION SLEEP(2) C C DIMENSION IS HMAX*WMAX*DMAX BYTE EXIT(HMAX*WMAX*DMAX), MAT(HMAX*WMAX*DMAX) INTEGER*4 LCOUNT(DMAX) C BYTE CLEAR(2) C C CHARACTER*200 INPUT BYTE INPUT(200) C COMMON /MAZECM/ STARTH,STARTW,STARTD,ENDH,ENDW,ENDD,NOBELL C C CLEAR IS A VT100 RESET C DATA CLEAR / 27, 'c' / C C START - SEE IF AN OLD GAME IS TO BE USED. C WRITE(5,10) 10 FORMAT(' WELCOME TO MAZE') C 20 WRITE(5,30) 30 FORMAT(' ARE YOU GOING TO PLAY A SAVED GAME? ',$) READ(5,40) NC,INPUT 40 FORMAT(Q,200(A1:)) C IF(INDEX(INPUT(1:NC),'Y').NE.0) GO TO 120 DO 500 INC=1,NC IF(INPUT(INC).EQ.'Y')GO TO 120 500 CONTINUE SAVE = 0 C C INPUT DIMENSION OF MAZE C 50 WRITE(5,60) HMAX 60 FORMAT(' PLEASE INPUT HEIGHT OF MAZE - DEFAULT = ',I2,' ',$) C READ(5,40) NC,INPUT C READ(INPUT,70,ERR=50) HEIGHT C 70 FORMAT(BNI2) READ(5,70,ERR=50)HEIGHT 70 FORMAT(I3) IF(HEIGHT.EQ.0) HEIGHT=HMAX IF(HEIGHT.LT.2) HEIGHT=2 IF(HEIGHT.GT.HMAX) HEIGHT=HMAX 80 WRITE(5,90) 90 FORMAT(' PLEASE INPUT WIDTH OF MAZE - DEFAULT = 80 ',$) C READ(5,40) NC,INPUT C READ(INPUT,70,ERR=80) WIDTH READ(5,70,ERR=80)WIDTH IF(WIDTH.EQ.0) WIDTH = 80 IF(WIDTH.LT.2) WIDTH=2 IF(WIDTH.GT.WMAX) WIDTH=WMAX 100 WRITE(5,110) 110 FORMAT(' PLEASE INPUT DEPTH OF MAZE - DEFAULT = 1 ',$) C READ(5,40) NC,INPUT C READ(INPUT,70,ERR=100) DEPTH READ(5,70,ERR=100)DEPTH IF(DEPTH.LE.0) DEPTH = 1 IF(DEPTH.GT.DMAX) DEPTH = DMAX NTERMS = HEIGHT * WIDTH * DEPTH C C GENERATE MAZE C CALL MAZGEN(EXIT,LCOUNT,HEIGHT,WIDTH,DEPTH) GO TO 180 C C READ IN OLD MAZE C 120 WRITE(5,130) 130 FORMAT(' INPUT SAVED FILE NAME ',$) READ(5,40) NC,INPUT INPUT(NC+1)=0 OPEN(UNIT=1,NAME=INPUT,TYPE='OLD',ERR=140, 1 FORM='UNFORMATTED',READONLY) GO TO 160 C 140 WRITE(5,150) 150 FORMAT(' SAVE FILE NOT FOUND') GO TO 20 160 READ(1) HEIGHT,WIDTH,DEPTH,STARTH,STARTW,STARTD, 1 ENDH,ENDW,ENDD NTERMS = HEIGHT * WIDTH * DEPTH READ(1) (EXIT(I),I=1,NTERMS) READ(1) (MAT (I),I=1,NTERMS) CLOSE(UNIT=1) C WRITE(5,170) 170 FORMAT( ' DO YOU WANT THE PATHS RESTORED? ',$) READ(5,40) NC,INPUT C IF(INDEX(INPUT(1:NC),'Y').NE.0) SAVE=1 DO 501 INC=1,NC IF(INPUT(INC).EQ.'Y')SAVE=1 501 CONTINUE C SPECIAL CASE TO PRINT ALL PATHS C IF(INDEX(INPUT(1:NC),'YES SOLUTIONS').NE.0) GO TO 240 DO 502 INC=1,NC IF(INPUT(INC).NE.'Y')GO TO 502 IF(INPUT(INC+1).NE.'E')GO TO 502 IF(INPUT(INC+2).NE.'S')GO TO 502 IF(INPUT(INC+3).NE.' ')GO TO 502 IF(INPUT(INC+4).NE.'S')GO TO 502 IF(INPUT(INC+5).NE.'O')GO TO 502 IF(INPUT(INC+6).NE.'L')GO TO 502 IF(INPUT(INC+7).NE.'U')GO TO 502 IF(INPUT(INC+8).NE.'T')GO TO 502 IF(INPUT(INC+9).NE.'I')GO TO 502 IF(INPUT(INC+10).NE.'O')GO TO 502 IF(INPUT(INC+11).NE.'N')GO TO 502 IF(INPUT(INC+12).EQ.'S')GO TO 240 502 CONTINUE C C MAZE DESCRIPTION C 180 WRITE(5,190) HEIGHT,WIDTH,DEPTH 190 FORMAT('0',' YOUR MAZE HAS A HEIGHT OF',I5,/, 1 ' AND A WIDTH OF',I5,/, 1 ' WITH A DEPTH OF',I5,//, 2 ' THE DIRECTION COMMANDS FOR MAZE ARE SINGLE LETTERS',/, 2 ' N(ORTH), U(P), OR 8 IS UP',/, 2 ' E(AST) , R(IGHT), OR 6 IS RIGHT',/, 2 ' S(OUTH), D(OWN), OR 2 IS DOWN',/, 2 ' W(EST) , L(EFT), OR 4 IS LEFT',/, 2 ' I(N) , OR 9 IS IN TO SCREEN',/, 2 ' O(UT) , OR 7 IS OUT OF SCREEN',/, 2 ' OR YOU CAN USE THE ARROW KEYS FOR DIRECTIONS',/, 3 ' THE COMMAND H(OME) RETURNS YOUR POSITION TO "S" OR "O"',/, 3 ' THE COMMAND Q(UIT) ENDS THE GAME',/, 3 ' THE COMMAND B(ELL) MAKES THE TERMINAL BEEP (DEFAULT)',/, 3 ' THE COMMAND M(UTE) TURNS OFF TERMINAL BEEPING',/, 3 ' THE COMMAND C(URRENT) PRINTS THE CURRENT LEVEL',/, 3 ' THE COMMAND Z(ERO) REFRESHES THE MAZE DISPLAY',/, 3 ' AFTER A Q(UIT) COMMAND YOU GET A CHANCE TO SAVE THE GAME',/, 4 ' YOU CAN MOVE ALONG BORDERS',//, 4 ' PRESS RETURN TO START') READ(5,40) NC,INPUT NOBELL = 0 C IF(INPUT(1:6).EQ.'NOBELL') OFFBEL = 1 IF((INPUT(1).EQ.'N').AND.(INPUT(2).EQ.'O') 1 .AND.(INPUT(3).EQ.'B').AND.(INPUT(4).EQ.'E') 1 .AND.(INPUT(5).EQ.'L').AND.(INPUT(6).EQ.'L'))OFFBEL=1 C C EXECUTE THE MAZE C IF(SAVE.EQ.1) GO TO 210 DO 200 I=1,NTERMS 200 MAT(I)=0 C 210 CALL MAZRUN(EXIT,MAT,HEIGHT,WIDTH,DEPTH) CALL NOCHR C C SAVE THE MAZE ON REQUEST C WRITE(5,220) 220 FORMAT(' DO YOU WANT TO SAVE THIS MAZE? ',$) READ(5,40) NC,INPUT C C IF(INDEX(INPUT(1:NC),'Y') .EQ.0) GO TO 260 DO 503 INC=1,NC IF(INPUT(INC).EQ.'Y')GO TO 265 503 CONTINUE GO TO 260 265 WRITE(5,230) 230 FORMAT(' PLEASE INPUT FILE NAME ',$) READ(5,40) NC,INPUT INPUT(NC+1)=0 OPEN(UNIT=1,NAME=INPUT,TYPE='NEW',FORM='UNFORMATTED') WRITE(1) HEIGHT,WIDTH,DEPTH,STARTH,STARTW,STARTD, 1 ENDH,ENDW,ENDD WRITE(1) (EXIT(I),I=1,NTERMS) WRITE(1) (MAT (I),I=1,NTERMS) CLOSE(UNIT=1) GO TO 260 C C PRINT THE SOLUTION TO A MAZE C 240 WRITE(5,250) HEIGHT,WIDTH,DEPTH 250 FORMAT('0',' YOUR MAZE HAS A HEIGHT OF',I5,/, 1 ' AND A WIDTH OF',I5,/, 1 ' WITH A DEPTH OF',I5,//, 4 ' PRESS RETURN TO START') READ(5,40) NC,INPUT C C PRINT MAZE C CALL MAZSOL(EXIT,MAT,HEIGHT,WIDTH,DEPTH) C C CLEAR SCREEN AND WAIT 2 SECONDS C 260 CALL MAZOUT(CLEAR,2,1,24,1,0,0,0) C CALL SYS$BINTIM( '0 ::02.00', SLEEP ) C CALL SYS$SCHDWK( , , SLEEP , ) C CALL SYS$HIBER CALL WAIT(2,2) STOP 'BYE FROM MAZE' END SUBROUTINE MAZGEN ( EXIT, LCOUNT, HEIGHT, WIDTH, DEPTH ) C C MAZGEN CREATES A MAZE IN EXIT C C MAZE IS CREATED BY GOING FROM A START LOCATION IN A C RANDOM WALK C SQUARES MAY ONLY BE ENTERED ONCE BUT CAN HAVE MULTIPLE EXITS C C MOVEMENT CONVENTION IS C 1 - SOUTH OR DOWN C 2 - EAST OR RIGHT C 4 - NORTH OR UP C 8 - WEST OR LEFT C 16 - IN A LEVEL C 32 - OUT A LEVEL C IMPLICIT INTEGER*4 (A-Z) C BYTE EXIT(HEIGHT,WIDTH,DEPTH) C DIMENSION XDIR(4), YDIR(4), IN(4), OUT(4),LCOUNT(DEPTH) C REAL SEED,SECNDS C COMMON /MAZECM/ STARTH,STARTW,STARTD,ENDH,ENDW,ENDD,NOBELL C DATA XDIR / 0, 1, 0,-1 / DATA YDIR / 1, 0,-1, 0 / DATA IN / 4, 8, 1, 2 / DATA OUT / 1, 2, 4, 8 / C C INITIALIZE AND PICK START AND END POSITIONS C SEED = SECNDS(0.) H = HEIGHT W = WIDTH D = DEPTH NENTER = 1 LMAX = H * W NMAX = LMAX * D DO 10 L=1,D LCOUNT(L) = 0 DO 10 J=1,W DO 10 I=1,H 10 EXIT (I,J,L) = 0 C STARTH = IRAN(SEED,1,H) STARTW = IRAN(SEED,1,W) STARTD = 1 20 CONTINUE ENDH = IRAN(SEED,1,H) ENDW = IRAN(SEED,1,W) ENDD = D IF(STARTH.EQ.ENDH.AND.STARTW.EQ.ENDW.AND.STARTD.EQ.ENDD) 1 GO TO 20 SY = STARTH SX = STARTW SD = STARTD LCOUNT(SD) = 1 C C START FILLING IN MAZE C 30 ODIR = 0 Y = SY X = SX L = SD 40 DIR = IRAN(SEED,1,4) C DO NOT GO BACK ON YOURSELF IF( ODIR .EQ. OUT(DIR) ) GO TO 40 C C TEND TO MAKE LONGER LINES WITH NLOOPS C NLOOPS = IRAN(SEED,1,DIR) NCOUNT=0 50 NY = YDIR(DIR) + Y NX = XDIR(DIR) + X IF(NY.LT.1.OR.NY.GT.H) GO TO 40 IF(NX.LT.1.OR.NX.GT.W) GO TO 40 IF( EXIT(NY,NX,L) .EQ. 0 ) GO TO 80 C C CHECK FOR DEAD END C DO 60 I=1,4 TY = Y + YDIR(I) TX = X + XDIR(I) IF(TY.LT.1.OR.TY.GT.H) GO TO 60 IF(TX.LT.1.OR.TX.GT.W) GO TO 60 C NOT DEAD END TRY AGAIN IF( EXIT(TY,TX,L) .NE. 0 ) GO TO 60 GO TO 40 60 CONTINUE C C DEAD END RETURN TO START UNLESS ALL DIRECTIONS ARE TAKEN C IF( Y.EQ.SY .AND. X.EQ. SX ) GO TO 70 GO TO 30 C C ALL STARTS FROM THIS STARTING POSITION ARE TAKEN C PICK A NEW STARTING POSITIONS UNTIL MAZE IS FULL C 70 SY = IRAN(SEED,1,H) SX = IRAN(SEED,1,W) IF( EXIT(SY,SX,L) .EQ. 0 ) GO TO 70 IF( SY.EQ.STARTH.AND.SX.EQ.STARTW.AND.L.EQ.STARTD) GO TO 70 IF( SY.EQ.ENDH .AND.SX.EQ.ENDW .AND.L.EQ.ENDD) GO TO 70 IF( SY.EQ.Y .AND.SX.EQ.X ) GO TO 70 C C FILL IN A LAYER AT A TIME C IF(LCOUNT(L).NE.LMAX) GO TO 30 SD = SD + 1 C EXIT(SY,SX, L) = IOR(EXIT(SY,SX, L),16) C EXIT(SY,SX,SD) = IOR(EXIT(SY,SX,SD),32) EXIT(SY,SX,L)=EXIT(SY,SX,L).OR.16 EXIT(SY,SX,SD)=EXIT(SY,SX,SD).OR.32 NENTER = NENTER + 1 LCOUNT(SD) = 1 GO TO 30 C C DIRECTION TO GO FOUND C SET POSITION AS HAVING BEEN ENTERED AND C SET EXIT ARRAY TO DIRECTIONS INVOLVED C 80 ODIR = IN(DIR) C EXIT(Y,X,L) = IOR(EXIT(Y,X,L),OUT(DIR)) C EXIT(NY,NX,L) = IOR(EXIT(NY,NX,L),IN(DIR)) EXIT(Y,X,L)=EXIT(Y,X,L).OR.OUT(DIR) EXIT(NY,NX,L)=EXIT(NY,NX,L).OR.IN(DIR) NENTER = NENTER + 1 LCOUNT(L) = LCOUNT(L)+1 C THE WAY OUT - ALL POINTS USED IF( NENTER .EQ. NMAX ) GO TO 90 Y = NY X = NX C C ONLY ALLOW THE END LOCATION TO BE ENTERED ONCE C IF(Y.EQ.ENDH.AND.X.EQ.ENDW.AND.L.EQ.ENDD) GO TO 30 NCOUNT=NCOUNT+1 IF(NCOUNT.LT.NLOOPS) GO TO 50 GO TO 40 C C OUT C 90 CONTINUE RETURN END SUBROUTINE MAZOUT( STRING, L, XOFF, Y, X, BOLD, REVERS, BLINK ) C***** C OUTPUTS -STRING- OF LENGTH -L- BYTES WITH BYTE NUMBER -XOFF- C OF STRING LOCATED AT CURSER LOCATION -X-, -Y-. C C BOLD, REVERS, BLINK ARE THE MODES TO OUTPUT THIS STRING C***** IMPLICIT INTEGER*4 (A-Z) C LOGICAL ANY C C CHARACTER*300 CC BYTE CC(300) C BYTE STRING(L), LINOUT(300), CHAR(10), ESCAPE EQUIVALENCE(CC,LINOUT(1)) C DATA CHAR/ '0', '1', '2', '3', '4', '5', '6', '7', '8', '9' / DATA ESCAPE/ 27 /, C1,C2,C3 / 0,0,0/ C C NL = X - XOFF + 1 NR = NL + L - 1 LENGTH = L ISTART = 1 NX = X NY = Y C C READJUST STRING LIMITS TO BE WITHIN SCREEN. IF STRING IS C COMPLETELY OUT OF SCREEN, THEN RETURN DOING NOTHING. C IF( NY.LT.1 .OR. NY.GT.24 ) RETURN IF( NR.LT.1 .OR. NL.GT.132 ) RETURN C C STRING (ALL OR PART) LIES IN THE SCREEN AREA. C IF( NL .GE. 1 ) GO TO 10 ISTART = 2 - NL NL = 1 LENGTH = LENGTH - ISTART + 1 C 10 IF( NR .LE. 132 ) GO TO 20 LENGTH = LENGTH - (NR-132) NR = 132 C C OK AT THIS POINT WE ARE GOING TO OUTPUT STRING(ISTART) THRU C STRING(ISTART+LENGTH-1) STARTING AT SCREEN LOCAT SCREEN ION (NL,NY) C C 20 LINOUT(1) = ' ' 20 LINOUT(1) = ESCAPE LINOUT(2) = '[' IOUT = 2 COORD = NY DO 40 I = 1,2 ANY = .FALSE. DO 30 J = 1,3 N = MOD( COORD/10**(3-J), 10 ) IF( N.EQ.0 .AND. .NOT.ANY ) GO TO 30 ANY = .TRUE. IOUT = IOUT + 1 LINOUT(IOUT) = CHAR(N+1) 30 CONTINUE IOUT = IOUT + 1 LINOUT(IOUT) = ';' COORD = NL 40 CONTINUE LINOUT(IOUT) = 'H' C C CHECK MODES AGAINST CURRENT MODES AND OUTPUT APPROPRIATE C MODE INDICATORS. C IF( C1.NE.0 .AND. BOLD.EQ.0 ) GO TO 80 IF( C2.NE.0 .AND. REVERS.EQ.0 ) GO TO 80 IF( C3.NE.0 .AND. BLINK.EQ.0 ) GO TO 80 IF( C1.EQ.BOLD .AND. C2.EQ.REVERS .AND. C3.EQ.BLINK )GO TO 120 C C OK SIMPLY ADD OUTPUT MODES C LINOUT(IOUT+1) = ESCAPE LINOUT(IOUT+2) = '[' IOUT = IOUT + 2 C IF( C1.EQ.BOLD ) GO TO 50 LINOUT(IOUT+1) = '1' LINOUT(IOUT+2) = ';' IOUT = IOUT + 2 C1 = BOLD C 50 IF( C2 .EQ. REVERS ) GO TO 60 LINOUT(IOUT+1) = '7' LINOUT(IOUT+2) = ';' IOUT = IOUT + 2 C2 = REVERS C 60 IF( C3 .EQ. BLINK ) GO TO 70 LINOUT(IOUT+1) = '5' LINOUT(IOUT+2) = ';' IOUT = IOUT + 2 C3 = BLINK C 70 LINOUT(IOUT) = 'm' GO TO 120 C C SOME OR ALL OF CURRENT MODES ARE NOT DESIRED, THUS C MUST DO A NORMAL FOLLOWED BY A RESET OF MODES DESIRED. C 80 LINOUT(IOUT+1) = ESCAPE LINOUT(IOUT+2) = '[' LINOUT(IOUT+3) = '0' LINOUT(IOUT+4) = ';' IOUT = IOUT + 4 C IF( BOLD .EQ. 0 ) GO TO 90 LINOUT(IOUT+1) = '1' LINOUT(IOUT+2) = ';' IOUT = IOUT + 2 C 90 C1 = BOLD IF( REVERS .EQ. 0 ) GO TO 100 LINOUT(IOUT+1) = '7' LINOUT(IOUT+2) = ';' IOUT = IOUT + 2 C 100 C2 = REVERS IF( BLINK .EQ. 0 ) GO TO 110 LINOUT(IOUT+1) = '5' LINOUT(IOUT+2) = ';' IOUT = IOUT + 2 C 110 C3 = BLINK LINOUT(IOUT) = 'm' C***** C OUTPUT THE STRING WITH ITS LEADER C***** 120 DO 130 I = 1,LENGTH LINOUT(IOUT+I) = STRING(ISTART+I-1) 130 CONTINUE IOUT = IOUT + LENGTH C***** C BACK UP CURSER ONE LINE IF AT LINE 24 C***** IF( NY .NE. 24 ) GO TO 140 LINOUT(IOUT+1) = ESCAPE LINOUT(IOUT+2) = 'M' IOUT = IOUT + 2 C***** C NOW READY TO OUTPUT THE STRING. C***** C 140 RC = LIB$PUT_OUTPUT( CC(1:IOUT) ) 140 WRITE(5,150)(CC(III),III=1,IOUT) 150 FORMAT(1H+,(A1),$) RETURN END INTEGER*4 FUNCTION IRAN( ISEED, I, J ) C***** C RETURNS A RANDOM NUMBER IN THE RANGE OF I THRU J. C SEED IS UPDATED AND THUS A VARIABLE MUST BE SENT. C***** REAL RAN INTEGER*2 ISEED(2) FN = J - I + 1 IRAN = I + IFIX( FN * RAN(ISEED(1),ISEED(2))) RETURN END SUBROUTINE MAZRUN(EXIT,MAT,HEIGHT,WIDTH,DEPTH) C C MAZRUN USES THE EXIT ARRAY TO CONTROL MAZE MOVEMENT C MAT ARRAY CONTAINS WHERE YOU HAVE BEEN C IMPLICIT INTEGER*4 (A-Z) C BYTE EXIT(HEIGHT,WIDTH,DEPTH) BYTE MAT (HEIGHT,WIDTH,DEPTH), ADD, MOVE(4,4) C DIMENSION XDIR(4), YDIR(4), OUT(6), SLEEP(2) C BYTE START(28),BELL,DEAD,LR132(10) BYTE SET(16) BYTE SCROL(8) C BYTE INPUT(200),NAME(10),PORT(6) C COMMON /MAZECM/ STARTH,STARTW,STARTD,ENDH,ENDW,ENDD,NOBELL C DATA XDIR / 0, 1, 0,-1 / DATA YDIR / 1, 0,-1, 0 / DATA OUT / 1, 2, 4, 8, 16, 32 / DATA BELL / 7 / C C ESCAPE SEQUENCES TO C ANSI MODE, ERASE SCREEN, ATTRIBUTES OFF, SCREEN NORMAL, C WRAP OFF, 80 COL., AND SPECIAL GRAPHICS C DATA START/ 27,'<',27,'[','2','J',27,'[','0','m',27,'[','?', 1 '5','l',27,'[','?','7','l', 27,'[','?','3','l',27,'(','0'/ C C GRAPHICS CHARACTERS TO USE FOR DRAWING LINES C DATA SET/' ', ' ', 'l', ' ', 'k', 'q', 'w', ' ', 1 'x', 'm', 't', 'j', 'u', 'v', 'n', 97 / C C ESCAPE SEQUENCE TO SET 132 CHARACTER LINE MODE C DATA LR132 / 27,'[','?','3','h' , 27,'[','?','5','h' / C C SET SCROLLING REGION TO LAST TWO LINES (23-24) C DATA SCROL / 27,'[','2','3',';','2','4','r' / DATA DEAD / 97 / DATA MOVE / 9, 5,-1, 3 1 ,10, 6, 3,-1 2 ,-1,12, 9,10 3 ,12,-1, 5, 6 / C C SET UP FOR QIO FROM TERMINAL C C STATUS = SYS$TRNLOG( 'SYS$INPUT' ,, NAME ,,, ) C PORT = NAME( 5:10 ) C STATUS = SYS$ASSIGN( PORT, CHAN ,, ) C IF( STATUS.NE.1 ) RETURN 1000 READ = 49 NOECHO = 64 CVLOW = 256 C C CLEAR SCREEN AND SHOW START AND END OF MAZE C CALL MAZOUT( START(1), 28, 1, 1,1, 0,0,0) IF(WIDTH.GT.80) CALL MAZOUT(LR132,10,1,1,1,0,0,0) CALL MAZOUT(SCROL,8,1,23,1,0,0,0) LOOP = 0 SOVER = 0 C C BORDER C 10 CONTINUE Y = STARTH X = STARTW L = STARTD 20 CONTINUE CALL MAZOUT(START(3),4,1,1,1,0,0,0) DO 40 I=1,HEIGHT CALL MAZOUT(' ',1,1, I,1 ,0,1,0) CALL MAZOUT(' ',1,1, I,WIDTH,0,1,0) IF(I.NE.1.AND.I.NE.HEIGHT) GO TO 40 DO 30 J=2,WIDTH-1 CALL MAZOUT(' ',1,1, I,J ,0,1,0) 30 CONTINUE 40 CONTINUE C C SHOW CURRENT STATUS OF MAZE SOLUTION C DO 50 J=1,WIDTH DO 50 I=1,HEIGHT IF((EXIT(I,J,L).AND.16).NE.0) CALL MAZOUT('O',1,1,I,J,1,1,1) IF(MAT(I,J,L).EQ.0) GO TO 50 IF(MAT(I,J,L).GT.0.AND.MAT(I,J,L).LT.16) 1 CALL MAZOUT(SET(MAT(I,J,L)),1,1,I,J,1,1,0) IF(MAT(I,J,L).LT.0) CALL MAZOUT('~',1,1,I,J,1,1,0) IF(MAT(I,J,L).EQ.64) CALL MAZOUT(SET(16),1,1,I,J,1,1,0) IF(MAT(I,J,L).GT.15.AND.MAT(I,J,L).LT.32) 1 CALL MAZOUT('O',1,1,I,J,1,1,0) IF(MAT(I,J,L).GT.31.AND.MAT(I,J,L).LT.64) 1 CALL MAZOUT('O',1,1,I,J,1,1,1) 50 CONTINUE IF(LOOP.NE.0.) CALL MAZOUT('O',1,1,Y,X,0,1,0) IF(L.EQ.ENDD) CALL MAZOUT( 'E',1,1,ENDH,ENDW,1,1,1) IF(L.EQ.STARTD) CALL MAZOUT( 'S',1,1,STARTH,STARTW,1,1,1) IF(INPUT(1).EQ.'Z')GO TO 55 HOMEH = Y HOMEW = X GO TO 60 55 IF((X.EQ.HOMEW).AND.(Y.EQ.HOMEH))GO TO 60 CALL MAZOUT('{',1,1,Y,X,0,1,1) 60 DEADE = 0 ODIR = 0 C C READ INPUT AND MOVE AS REQUESTED C ESC = 0 OPT = READ + NOECHO + CVLOW 70 CALL MAZOUT(' ',1,1,24,1,0,0,0) C C STATUS = SYS$QIOW( , %VAL(CHAN), %VAL(OPT),,,, C 1 %VAL(%LOC(INPUT)), %VAL(1),,,, ) C IF( STATUS .NE. 1 ) RETURN CALL INCHR(INPUT) C 80 FORMAT(Q,A) IF( ESC .EQ. 1 ) GO TO 140 IF((INPUT(1)) .EQ. 27 ) GO TO 130 IF(INPUT(1) .EQ.'Q') RETURN IF(INPUT(1) .EQ.'B') GO TO 90 IF(INPUT(1) .EQ.'M') GO TO 100 IF(INPUT(1) .EQ.'C' ) GO TO 110 IF(INPUT(1) .EQ.'Z')GO TO 20 IF(INPUT(1).NE.'H') GO TO 160 IF(Y.EQ.HOMEH.AND.X.EQ.HOMEW) GO TO 60 SOVER=1 ADD = -1 GO TO 220 90 NOBELL = 0 GO TO 70 100 NOBELL = 1 GO TO 70 110 WRITE(5,120) L 120 FORMAT( ' CURRENT LEVEL IS ',I2) GO TO 70 130 ESC = 1 GO TO 70 140 IF(INPUT(1) .EQ. '[' ) GO TO 170 ESC=0 GO TO 70 150 SOVER = 0 Y = HOMEH X = HOMEW GO TO 60 C C FIND DIRECTION TO GO C 160 DIR = 0 C IF((INPUT(1)).EQ.27) GO TO 170 IF(INPUT(1).EQ.'S'.OR.INPUT(1).EQ.'D') DIR=1 IF(INPUT(1).EQ.'E'.OR.INPUT(1).EQ.'R') DIR=2 IF(INPUT(1).EQ.'N'.OR.INPUT(1).EQ.'U') DIR=3 IF(INPUT(1).EQ.'W'.OR.INPUT(1).EQ.'L') DIR=4 IF(INPUT(1).EQ.'2') DIR=1 IF(INPUT(1).EQ.'6') DIR=2 IF(INPUT(1).EQ.'8') DIR=3 IF(INPUT(1).EQ.'4') DIR=4 IF(INPUT(1).EQ.'I'.OR.INPUT(1).EQ.'9') DIR=5 IF(INPUT(1).EQ.'O'.OR.INPUT(1).EQ.'7') DIR=6 GO TO 180 C C CHECK ARROW KEYS ( DID NOT HAVE TIME TO MAKE THIS WORK ) C 170 CALL INCHR(INPUT) IF(INPUT(1).EQ.'A') DIR=3 IF(INPUT(1).EQ.'B') DIR=1 IF(INPUT(1).EQ.'C') DIR=2 IF(INPUT(1).EQ.'D') DIR=4 ESC = 0 180 IF(DIR.NE.0) GO TO 200 C C COMMAND NOT RECOGNIZED C WRITE(5,190) 190 FORMAT(' TRY AGAIN ') GO TO 70 C C SEE IF DIRECTION IS LEGAL C 200 IF((EXIT(Y,X,L).AND.OUT(DIR)) .NE. 0 ) GO TO 210 IF(NOBELL .NE. 0 ) GO TO 70 CALL MAZOUT( BELL ,1,1, 24,1, 0,0,0 ) GO TO 70 C C MOVE KEEP MOVEMENT ARRAY MAT UP TO DATE C 210 IF(Y.EQ.STARTH.AND.X.EQ.STARTW.AND.L.EQ.STARTD) GO TO 230 IF(DEADE.EQ.1) GO TO 230 ADD = OUT(DIR) IF(ODIR.NE.0.AND.DIR.LT.5) ADD = MOVE(ODIR,DIR) IF(ODIR.EQ.0) ADD = 0 220 IF(MAT(Y,X,L).EQ.-1) MAT(Y,X,L) = 0 IF(ADD.EQ.-1 .AND. MAT(Y,X,L).EQ.0 ) MAT(Y,X,L) = ADD C IF(ADD.NE.-1) MAT(Y,X,L) = IOR(MAT(Y,X,L),ADD) IF(ADD.NE.-1)MAT(Y,X,L)=MAT(Y,X,L).OR.ADD IF(MAT(Y,X,L).GT.0.AND.MAT(Y,X,L).LT.16) 1 CALL MAZOUT(SET(MAT(Y,X,L)),1,1,Y,X,1,1,0) IF(MAT(Y,X,L).LT.0) CALL MAZOUT( '~' ,1,1,Y,X,1,1,0) 230 IF(SOVER.EQ.1) GO TO 150 IF( DIR.LT.5 ) GO TO 240 C C CHANGE LEVELS C IF( DIR.EQ.5 ) L = L+1 IF( DIR.EQ.6 ) L = L-1 MAT(Y,X,L) = OUT(DIR) LOOP = LOOP + 1 GO TO 20 240 Y = Y + YDIR(DIR) X = X + XDIR(DIR) IF(Y.EQ.STARTH.AND.X.EQ.STARTW.AND.L.EQ.STARTD) GO TO 70 IF(MAT(Y,X,L).LT.16) CALL MAZOUT('{',1,1,Y,X,0,1,1) DEADE = 0 ODIR = DIR IF(Y.EQ.ENDH.AND.X.EQ.ENDW.AND.L.EQ.ENDD) GO TO 270 C C CHECK FOR DEAD END C DO 250 I=1,6 IF( EXIT(Y,X,L) .EQ. OUT(I) ) GO TO 260 250 CONTINUE GO TO 70 C C DEAD END C 260 CALL MAZOUT(DEAD,1,1,Y,X,0,0,0) MAT(Y,X,L) = 64 DEADE = 1 GO TO 70 270 CONTINUE C C SUCCESS - END FOUND C DO 290 I=1,6 J=MOD(I,2) CALL MAZOUT('E',1,1,ENDH,ENDW,1,J,1) CALL MAZOUT(' ',1,1,24,1,0,J,1) WRITE(5,280) 280 FORMAT(' SUCCESS SUCCESS SUCCESS' ) C CALL SYS$BINTIM( '0 ::00.50', SLEEP ) C CALL SYS$SCHDWK( , , SLEEP , ) C CALL SYS$HIBER CALL WAIT(2,1) 290 CONTINUE RETURN END SUBROUTINE MAZSOL(EXIT,MAT,HEIGHT,WIDTH,DEPTH) C C MAZSOL SHOWS ALL POSSIABLE PATHS IN MAZE C IMPLICIT INTEGER*4 (A-Z) C BYTE EXIT(HEIGHT,WIDTH,DEPTH) BYTE MAT (HEIGHT,WIDTH,DEPTH), ADD, MOVE(4,4) DIMENSION XDIR(4), YDIR(4), OUT(4), SLEEP(2) C BYTE START(28),BELL,DEAD,LR132(10) BYTE SET(16) BYTE SCROL(8) C C CHARACTER*200 INPUT C COMMON /MAZECM/ STARTH,STARTW,STARTD,ENDH,ENDW,ENDD,NOBELL C DATA XDIR / 0, 1, 0,-1 / DATA YDIR / 1, 0,-1, 0 / DATA OUT / 1, 2, 4, 8 / DATA BELL / 7 / DATA START/ 27,'<',27,'[','2','J',27,'[','0','m',27,'[','?', 1 '5','l',27,'[','?','7','l', 27,'[','?','3','l',27,'(','0'/ DATA SET/' ', ' ', 'l', ' ', 'k', 'q', 'w', ' ', 1 'x', 'm', 't', 'j', 'u', 'v', 'n', 97 / DATA LR132 / 27,'[','?','3','h' , 27,'[','?','5','h' / DATA SCROL / 27,'[','2','3',';','2','4','r' / DATA DEAD / 97 / DATA MOVE / 0, 3, 9, 5 1 , 3, 0,10, 6 2 , 9,10, 0,12 3 , 5, 6,12, 0 / C C CLEAR SCREEN AND SHOW START AND END OF MAZE C CALL MAZOUT( START(1), 28, 1, 1,1, 0,0,0) IF(WIDTH.GT.80) CALL MAZOUT(LR132,10,1,1,1,0,0,0) CALL MAZOUT(SCROL,8,1,23,1,0,0,0) C C BORDER C DO 70 L = 1,DEPTH IF(L.EQ.ENDD) CALL MAZOUT( 'E',1,1,ENDH,ENDW,1,1,1) IF(L.EQ.STARTD) CALL MAZOUT( 'S',1,1,STARTH,STARTW,1,1,1) C C LOOP OVER MAZE C DO 40 X=1,WIDTH DO 40 Y=1,HEIGHT MAT(Y,X,L) = 0 IF(Y.EQ.STARTH.AND.X.EQ.STARTW.AND.L.EQ.STARTD) GO TO 40 IF(Y.EQ.ENDH .AND.X.EQ.ENDW .AND.L.EQ.ENDD) GO TO 40 C C CHECK FOR DEAD END C DO 20 ODIR=1,4 IF( EXIT(Y,X,L) .EQ. OUT(ODIR) ) GO TO 30 IF((EXIT(Y,X,L).AND.OUT(ODIR)) .EQ. 0 ) GO TO 20 DO 10 DIR=1,4 IF(DIR.EQ.ODIR) GO TO 10 IF((EXIT(Y,X,L).AND.OUT(DIR)) .EQ. 0 ) GO TO 10 ADD = MOVE(ODIR,DIR) C MAT(Y,X,L) = IOR(MAT(Y,X,L),ADD) MAT(Y,X,L)=MAT(Y,X,L).OR.ADD 10 CONTINUE 20 CONTINUE IF(EXIT(Y,X,L).LT.16) CALL MAZOUT(SET(MAT(Y,X,L)),1,1,Y,X,1,1,0) IF((EXIT(Y,X,L).AND.16).NE.0) CALL MAZOUT('O',1,1,Y,X,1,1,1) IF((EXIT(Y,X,L).AND.32).NE.0) CALL MAZOUT('O',1,1,Y,X,1,1,0) GO TO 40 C C DEAD END C 30 CALL MAZOUT(DEAD,1,1,Y,X,0,0,0) 40 CONTINUE C C SUCCESS - END FOUND C CALL MAZOUT(' ',1,1,24,1,0,0,0) WRITE(5,50) 50 FORMAT(' PRESS RETURN TO CONTINUE OR FINISH') READ(5,60) INPUT 60 FORMAT(I1) 70 CONTINUE RETURN END