PROGRAM PACMAN IMPLICIT INTEGER (A-Z) # # THIS IS THE MAIN CONTROL PROGRAM FOR PACMAN # EXTERNAL *INPAST,*CNTRLC INCLUDE/NL SY:UVT100.DAT INCLUDE/NL SY:PACMAN.CMN PARAMETER TMREFN=1 BYTE NOWRAP(2) # # MOVE IS THE SPEED REGULATOR FOR THE PACMAN AND THE MONSTERS. # TOP SPEED (100%) IS DEFINED AS MOVEMENT IN EVERY CYCLE # IN THE HORIZONTAL DIRECTION, AND MOVEMENT IN EVERY OTHER # CYCLE IN THE VERTICAL DIRECTION. (TO CORRECT FOR VT100 SKEW - # EACH SCREEN POSITION ON THE VT100 IS APPROXIMATELY TWICE AS HIGH # AS IT IS WIDE). OTHER SPEEDS ARE IN RELATION TO TOP SPEED. THUS, # WHEN IT IS NECESSARY TO DETERMINE IF MOTION IS ALLOWED ON THE # CURRENT CYCLE, WE FIRST LOOK AT THE CURRENT DIRECTION OF MOTION # AND SEE IF THAT IS ALLOWED THIS CYCLE, AND, IF OTHER THAN 100% # SPEED IS DESIRED, WE ALSO LOOK AT THE APPROPRIATE ENTRY IN MOVE TO # SEE IF MOTION FOR THE DESIRED SPEED IS ALLOWED. MOVE IS INDEXED BY # CYCLE NUMBER (COLUMN) AND BY RATE OF SPEED (ROW). # # THE ROWS ARE DEFINED AS FOLLOWS: # ROW 1 - 100% OF TOP SPEED (UP) # ROW 2 - 100% OF TOP SPEED (DOWN) # ROW 3 - 50% OF TOP SPEED # ROW 4 - 100% OF TOP SPEED (LEFT) # ROW 5 - 92% OF TOP SPEED # ROW 6 - 75% OF TOP SPEED # ROW 7 - 83% OF TOP SPEED # ROW 8 - 100% OF TOP SPEED (RIGHT) # ROW 9 - 67% OF TOP SPEED DATA MOVE / 0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1, 0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1, 1,1,0,0,1,1,0,0,1,1,0,0,1,1,0,0,1,1,0,0,1,1,0,0, 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, 1,1,1,1,1,1,1,1,0,1,1,1,1,1,1,1,1,1,1,0,1,1,1,1, 0,1,1,1,1,0,1,1,0,1,1,1,1,0,1,1,0,1,1,1,1,0,1,1, 1,0,1,1,1,1,1,1,0,1,1,1,1,0,1,1,1,1,1,1,0,1,1,1, 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, 1,0,1,0,1,1,1,0,1,0,1,1,1,0,1,0,1,1,1,0,1,0,1,1 / % DATA LMAN / "140,"145,"141 / % DATA CMAN / "140,"144,"141 / % DATA FMAN / "140,"143,"141 / % DATA NMAN / "140,"150,"141 / % DATA EATCHR / "62,"64,"70,"130 / DATA EATSCO / 200,400,800,1600 / DATA FRUDSR / 18,18,18,18,18,20,20,20,20,20, 22,22,22,22,22,24,24,24,24,24 / DATA FRUDSC / 70,72,74,76,78,70,72,74,76,78, 70,72,74,76,78,70,72,74,76,78 / DATA FRUSCO / 100,300,500,700,1000,2000 / % DATA FRUCHR / "101,"102,"103,"104,"105,"106 / % DATA FRUTBL / 20*"40 / % DATA NOWRAP / "24,0 / # # PACMAN WORKS ON A 24-CYCLE 'CLOCK'. A TIMER IS SET TO ENSURE THAT # NO CYCLE TAKES LESS THAN 100 MILLISECONDS. IN PRACTICE, MOST # CYCLES TAKE ABOUT 150 MILLISECONDS (AT 9600 BAUD ON AN 11/44). # DURING EACH CYCLE, ONE MOVEMENT IS ATTEMPTED FOR PACMAN AND FOR EACH # MONSTER, AND ALL DECISIONS BASED ON BOARD STATE ARE MADE. # CYCTIM = 6 #NOMINAL CYCLE TIME (100 MS) PRITIM = CYCTIM * 30 #IN PRISON TIME GOODTM = CYCTIM * 40 #GOOD STATE TIME BLNKTM = CYCTIM * 20 #BLINK STATE TIME FRUTIM = CYCTIM * 150 #DELAY TIME FOR FRUIT FRULTH = CYCTIM * 50 #TIME FRUIT STAYS DISPLAYED OLDSCO = -1 OLDCNT = -1 PACCNT = 3 #START WITH 3 PACMEN # # ATTACH AND SET UP TERMINAL # CALL GETADR(PRL,NOWRAP) PRL(2) = 2 CALL WTQIO(SFSMC,5,2,,,PRL) #SET /NOWRAP=TI: OPEN (UNIT=5,CARRIAGECONTROL='NONE') #OPEN VT100 ON LUN 5 CALL GETADR(PRL(1),INPAST) #UNSOLICITED INPUT AST PRL(2) = 0 CALL GETADR(PRL(3),CNTRLC) #CONTROL-C AST CALL WTQIO(IOATA,5,1,,,PRL) #ATTACH VT100 PRL(2) = 1 #SET UP PRL FOR IO.WVB QIOS PRL(3) = 0 CALL DSASTR #DISABLE AST RECOGNITION CALL UVT100(ANSI) #SET VT100 TO ANSI MODE CALL UVT100(RM,8) #DISABLE VT100 AUTOREPEAT CALL UVT100(RM,3) #SET VT100 TO 80 COLUMN WIDTH CALL UVT100(RM,5) #SCREEN TO BLACK BACKGROUND CALL UVT100(ED,2) #ERASE SCREEN CALL UVT100(CUP,12,37) #CENTER OF SCREEN WRITE (5,300) #DISPLAY "PACMAN" CALL UVT100(CUP,1,1) #HOME CURSOR CALL RESTAR #START FIRST BOARD # # MAIN CONTROL LOOP. EACH PASS THROUGH IS ONE 'CYCLE'. THE CURRENT # CYCLE NUMBER IS INCREMENTED. (THERE ARE 24 CYCLES. EACH MAN IS # ONLY ALLOWED MOTION ON CERTAIN CYCLES, SO WE CAN SIMULATE VARIOUS # SPEEDS). # REPEAT [ CALL MARK(TMREFN,CYCTIM,1) #START 100-MS CLOCK CYCLE = CYCLE + 1 #INCREMENT CURRENT CYCLE NO. IF (CYCLE > 24) #WRAPAROUND TO CYCLE #1 CYCLE = 1 CALL DSASTR #DISABLE AST RECOGNITION CALL PACMOV #CONTROL PACMAN MOTION IF (DOTCNT <= 0) [ #IF OUT OF DOTS, RESET BOARD CALL RESTAR OLDSCO = -1 #FORCE SCORE AND NUMBER OLDCNT = -1 #OF PACMEN LEFT TO DISPLAY ] IF (SCORE != OLDSCO) [ #IF SCORE HAS CHANGED, CALL UVT100(CUP,5,70) #POSITION CURSOR AND WRITE (5,200) SCORE #UPDATE SCORE ON VT100 OLDSCO = SCORE #SAVE CURRENT SCORE ] IF (STATE != EATEN) CALL LEFTY #PROCESS LEFTY'S MOTION IF (STATE != EATEN) CALL CURLY #PROCESS CURLY'S MOTION IF (STATE != EATEN) CALL FLUFFY #PROCESS FLUFFY'S MOTION IF (STATE != EATEN) CALL NELLIE #PROCESS NELLIE'S MOTION IF (STATE == EATEN .AND. GAMOVR == 0) [ CALL RESTAR #RESTART IF PACMAN EATEN OLDSCO = -1 ] IF (PACCNT != OLDCNT) [ #IF NO. OF PACMEN CHANGED, CALL UVT100(CUP,10,70) #POSITION CURSOR AND CALL UVT100(EL,0) #UPDATE NUMBER ON VT100 IF (PACCNT > 1) [ DO I = 1,PACCNT-1 [ CALL GETADR(PRL,PMAN) CALL WTQIO(IOWVB,5,2,,,PRL) CALL GETADR(PRL,SPACE) CALL WTQIO(IOWVB,5,2,,,PRL) ] ] OLDCNT = PACCNT #SAVE NEW COUNT OF PACMEN ] # # TEST FOR CHANGES IN FRUIT DISPLAY STATUS. (AT APPROPRIATE # TIMES DISPLAY OR UNDISPLAY FRUIT) # IF (FRUIT == 0) [ #IF FRUIT NOT DISPLAYED IF (FRUON < TIMER) [ #TEST IF TIME TO DISPLAY FRUIT = 1 CALL UVT100(CUP,FRUROW,FRUCOL) CALL GETADR(PRL,FRUCHR(BOARD)) CALL WTQIO(IOWVB,5,2,,,PRL) #DISPLAY FRUIT FRUOFF = TIMER + FRULTH ] ] ELSE [ #IF FRUIT DISPLAYED IF (FRUOFF < TIMER) [ #TEST IF TIME TO UNDISPLAY FRUIT = 0 CALL UVT100(CUP,FRUROW,FRUCOL) CALL GETADR(PRL,SPACE) CALL WTQIO(IOWVB,5,2,,,PRL) #UNDISPLAY FRUIT FRUON = TIMER + FRUTIM ] ] CALL ENASTR #ENABLE AST RECOGNITION # # TEST FOR STATE CHANGES # IF (STATE == GOOD) [ #IF STATE IS 'GOOD', IF (STATIM+GOODTM <= TIMER) [ #AND TIMER HAS RUN OUT, STATE = BLINK #SET STATE TO 'BLINK' STATIM = TIMER ] ] ELSE IF (STATE == BLINK) [ #ELSE IF STATE IS 'BLINK', IF (STATIM+BLNKTM <= TIMER) [ #AND TIMER HAS RUN OUT, STATE = BAD #SET STATE TO 'BAD'. EATCNT = 0 #CLEAR MONSTERS EATEN COUNT ] ] CALL WAITFR(TMREFN) #WAIT FOR CYCLE TIMER COMPLETE TIMER = TIMER + CYCTIM #INCREMENT ELPASED CYCLE TIME ] UNTIL (NEWDIR == -1 .OR. GAMOVR == 1) #EXIT ON CONTROL-C OR GAMEOVER CALL DSASTR(STATUS) #DISABLE AST RECOGNITION CALL GETADR(PRL,SHFIN) #RESET NORMAL CHARACTER SETS CALL WTQIO(IOWVB,5,2,,,PRL) IF (GAMOVR == 1) [ #GAME IS OVER CALL UVT100(CUP,23,70) WRITE (5,400) ] ELSE #EXITED ON A CONTROL-C CALL UVT100(ED,2) #ERASE SCREEN CALL UVT100(CUP,1,1) #HOME CURSOR CALL EXIT #EXIT TASK 200 FORMAT (I6) 300 FORMAT ("PACMAN") 400 FORMAT ("GAME OVER") END