PROGRAM PACMAN IMPLICIT INTEGER (A-Z) # # THIS IS THE MAIN CONTROL CODE FOR PACMAN # ######################################################################### # # # AUTHOR: GLEN HOFFING # # RCA GOVERNMENT COMMUNICATIONS SYSTEMS # # FRONT AND COOPER STS. # # CAMDEN, NJ 08102 # # # # DATE: 17-MAR-82 # # # ######################################################################### # EXTERNAL *INPAST,*CNTRLC INCLUDE/NL SY:UVT100.DAT INCLUDE/NL SY:PACMAN.CMN PARAMETER TMREFN=1 BYTE NOWRAP(2) # # -- RELATIVE SPEEDS -- # # PACMAN MOVES AT 100% OF TOP SPEED NORMALLY, AND AT 75% WHEN # HE IS EATING DOTS. LEFTY MOVES AT 92% OF TOP SPEED AND THE OTHER # THREE MONSTERS AT 83%. WHEN TRAVELING THROUGH A TUNNEL, THE # MONSTERS MOVE AT 50%. WHEN THEY ARE BEING CHASED BY PACMAN, # THEY ALL MOVE AT 67%. # # 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 / 16,16,16,16,16,18,18,18,18,18, 20,20,20,20,20,22,22,22,22,22 / 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 / CALL TIMCHK #CHECK LEGAL GAME-PLAYING TIME # # PACMAN WORKS ON A 24-CYCLE 'CLOCK'. A TIMER IS SET TO ENSURE THAT # EACH CYCLE TAKES CYCTIM ONE/SIXTIETHS OF A SECOND. CYCTIM IS SET TO # SEVEN ON THE FIRST BOARD, AND DECREASES TO FOUR BY THE SIXTH BOARD. # DURING EACH CYCLE, ONE MOVEMENT IS ATTEMPTED FOR PACMAN AND FOR EACH # MONSTER, AND ALL DECISIONS BASED ON BOARD STATE ARE MADE. # 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,2,,,PRL) #ATTACH VT100 PRL(3) = 0 CALL UVT100(ANSI) #SET VT100 TO ANSI MODE CALL UVT100(RM,8) #DISABLE VT100 AUTOREPEAT CALL UVT100(RM,5) #SCREEN TO BLACK BACKGROUND CALL UVT100(ED,2) #ERASE SCREEN CALL UVT100(SCS,0,1) #LOAD ASCII CHARACTER SET CALL UVT100(SCS,1,2) #LOAD GRAPHICS CHARACTER SET OUTBUF(LEN+1) = SHFOUT LEN = LEN + 1 CALL GETADR(PRL,OUTBUF) PRL(2) = LEN CALL WTQIO(IOWVB,5,2,,,PRL) LEN = 0 # # WRITE INTRODUCTIONS # CALL UVT100(CUP,8,35) PRL(2) = LEN CALL WTQIO(IOWVB,5,2,,,PRL) LEN = 0 WRITE (5,500) LMAN(BAD) CALL UVT100(CUP,10,35) PRL(2) = LEN CALL WTQIO(IOWVB,5,2,,,PRL) LEN = 0 WRITE (5,600) CMAN(BAD) CALL UVT100(CUP,12,35) PRL(2) = LEN CALL WTQIO(IOWVB,5,2,,,PRL) LEN = 0 WRITE (5,700) FMAN(BAD) CALL UVT100(CUP,14,35) PRL(2) = LEN CALL WTQIO(IOWVB,5,2,,,PRL) LEN = 0 WRITE (5,800) NMAN(BAD) CALL WAIT(1,2) DO I = 10,60 [ CALL UVT100(CUP,21,I) CALL UVT100(EL,2) PRL(2) = LEN CALL WTQIO(IOWVB,5,2,,,PRL) LEN = 0 WRITE (5,900) NMAN(BAD),FMAN(BAD),CMAN(BAD),LMAN(BAD),PMAN ] CALL UVT100(EL,2) 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 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 ENCODE(6,200,OUTBUF(LEN+1)) SCORE #UPDATE SCORE ON VT100 LEN = LEN + 6 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 [ OUTBUF(LEN+1) = PMAN LEN = LEN + 1 OUTBUF(LEN+1) = SPACE LEN = LEN + 1 ] ] 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 .AND. FRUBRD < 5) [ #TEST IF TIME TO DISPLAY FRUIT = 1 #(LIMIT 5 FRUIT PER BOARD) CALL UVT100(CUP,FRUROW,FRUCOL) OUTBUF(LEN+1) = FRUCHR(BOARD) #DISPLAY FRUIT LEN = LEN + 1 FRUOFF = TIMER + FRULTH ] ] ELSE [ #IF FRUIT DISPLAYED IF (FRUOFF < TIMER) [ #TEST IF TIME TO UNDISPLAY FRUIT = 0 FRUBRD = FRUBRD + 1 CALL UVT100(CUP,FRUROW,FRUCOL) OUTBUF(LEN+1) = SPACE #UNDISPLAY FRUIT LEN = LEN + 1 FRUON = TIMER + FRUTIM ] ] # # 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 UVT100(CUP,LROW,LCOL) #REDISPLAY MONSTERS OUTBUF(LEN+1) = LMAN(BAD) LEN = LEN + 1 CALL UVT100(CUP,CROW,CCOL) OUTBUF(LEN+1) = CMAN(BAD) LEN = LEN + 1 CALL UVT100(CUP,FROW,FCOL) OUTBUF(LEN+1) = FMAN(BAD) LEN = LEN + 1 CALL UVT100(CUP,NROW,NCOL) OUTBUF(LEN+1) = NMAN(BAD) LEN = LEN + 1 ] ] CALL GETADR(PRL,OUTBUF) PRL(2) = LEN CALL WTQIO(IOWVB,5,2,,,PRL) LEN = 0 CALL WAITFR(TMREFN) #WAIT FOR CYCLE TIMER COMPLETE TIMER = TIMER + CYCTIM #INCREMENT ELAPSED CYCLE TIME ] UNTIL (NEWDIR == -1 .OR. GAMOVR == 1) #EXIT ON CONTROL-C OR GAMEOVER OUTBUF(LEN+1) = SHFIN LEN = LEN + 1 IF (GAMOVR == 1) [ #GAME IS OVER CALL UVT100(CUP,23,70) CALL GETADR(PRL,OUTBUF) PRL(2) = LEN CALL WTQIO(IOWVB,5,2,,,PRL) LEN = 0 WRITE (5,1000) ] ELSE #EXITED ON A CONTROL-C CALL UVT100(ED,2) #ERASE SCREEN CALL UVT100(SM,8) #REENABLE VT100 AUTOREPEAT CALL UVT100(CUP,1,1) #HOME CURSOR PRL(2) = LEN CALL WTQIO(IOWVB,5,2,,,PRL) LEN = 0 CALL EXIT #EXIT TASK 200 FORMAT (I6) 500 FORMAT (A1," - LEFTY") 600 FORMAT (A1," - CURLY") 700 FORMAT (A1," - FLUFFY") 800 FORMAT (A1," - NELLIE") 900 FORMAT (A1,2X,A1,2X,A1,2X,A1,6X,A1) 1000 FORMAT ("GAME OVER") END