! ************************** AMUS Program Label ******************************
! Filename: PAC65.BAS                                       Date: 05/07/90
! Category: GAME         Hash Code: 002-046-217-466      Version: 1.0(100)
! Initials: ULTR/AM      Name: DAVID PALLMANN
! Company: ULTRASOFT CORPORATION                   Telephone #: 5163484848
! Related Files: PAC65.BAS/.RUN; PAC65.SBR; PAC65B.SBR
! Min. Op. Sys.: AMOSL 1.3D                    Expertise Level: BEG
! Special: AM-65 terminal in native mode ONLY.
! Description: Pacman-like game for the AM-65.  First draft, improvements
! will follow.  Source for .SBRs is not available.
!
! ****************************************************************************
       PROGRAM PAC65, 1.0(100)

       MAP1 TEXT,S,80
       MAP1 PR,F,6
       MAP1 PC,F,6
       MAP1 GR(4),F,6
       MAP1 GC(4),F,6
       MAP1 GHOST,F,6
       MAP1 BOARD(24),S,80
       MAP1 I,F,6
       MAP1 J,F,6
       MAP1 CHAR,S,1
       MAP1 GHOSTS,F,6
       MAP1 DIR,F,6
       MAP1 RETRIES,F,6
       MAP1 GHOST'RETRIES,F,6
       MAP1 DELAY,F,6
       MAP1 GHOST'DELAY,F,6
       MAP1 FLAG,F,6
       MAP1 SCORE,F,6
       MAP1 POS,F,6
       MAP1 GAME,F,6
       MAP1 ALERT,F,6
       MAP1 DOTS,F,6
       MAP1 FRUIT'LEVEL,F,6
       MAP1 FRUIT'FLAG,F,6
       MAP1 FRUIT'DELAY,F,6


INIT:   GAME = 0

NEW'GAME:
       GAME = GAME+1
       RANDOMIZE
       SCORE = 0
       GHOST'DELAY = 5 : DELAY = 5
       GHOST'RETRIES = 2
       SCORE = 0
       CALL NEWGAME
       XCALL PAC65                       ! load graphics characters
!!!!!   CALL INTRO
       GOTO BEGIN'GAME

NEW'SCREEN:
       CALL NEWGAME
       GHOST'RETRIES = GHOST'RETRIES + 1
       IF GHOST'DELAY>0 THEN GHOST'DELAY = GHOST'DELAY-1
       DELAY = GHOST'DELAY

BEGIN'GAME:
       CALL BACKGROUND
       PRINT TAB(PR,PC); "R";
       FOR GHOST = 1 TO 4
               PRINT TAB(GR(GHOST),GC(GHOST)); "G";
               NEXT GHOST


READY:  PRINT TAB(22,1); "ready!";
R1:     XCALL PAC65B, CHAR
       IF CHAR="" THEN GOTO R1
       PRINT TAB(22,1); "0"; SPACE(8);
       GOTO GM1

GET'MOVE:
       XCALL PAC65B, CHAR
GM1:    IF CHAR="" THEN GOTO MOVE'GHOST
       IF CHAR=CHR(12) THEN GOTO MOVE'RIGHT
       IF CHAR=CHR(11) THEN GOTO MOVE'UP
       IF CHAR=CHR(10) THEN GOTO MOVE'DOWN
       IF CHAR=CHR(8) THEN GOTO MOVE'LEFT
       IF CHAR=CHR(27) THEN GOTO EXIT
       GOTO GET'MOVE

MOVE'LEFT:
       CHAR = BOARD(PR)[PC-2;1]
       IF CHAR<>" " AND CHAR<>"o" AND CHAR<>"O" AND CHAR<>"#" THEN GOTO GET'MOVE
       PRINT TAB(PR,PC); " ";
       PC = PC-2
       PRINT TAB(PR,PC); "L";
       IF CHAR<>"#" THEN BOARD(PR)[PC;1] = " "
       IF CHAR="#" THEN GOTO TRANSPORT'LEFT
       CALL RECORD'SCORE
       GOTO CHECK'END

TRANSPORT'LEFT:
       PRINT TAB(PR,PC); " ";
       PC = LEN(BOARD(PR))
       PRINT TAB(PR,PC); "L";
       GOTO CHECK'END

MOVE'RIGHT:
       CHAR = BOARD(PR)[PC+2;1]
       IF CHAR<>" " AND CHAR<>"o" AND CHAR<>"O" AND CHAR<>"#" THEN GOTO GET'MOVE
       PRINT TAB(PR,PC); " ";
       PC = PC+2
       PRINT TAB(PR,PC); "R";
       IF CHAR<>"#" THEN BOARD(PR)[PC;1] = " "
       IF CHAR="#" THEN GOTO TRANSPORT'RIGHT
       CALL RECORD'SCORE
       GOTO CHECK'END

TRANSPORT'RIGHT:
       PRINT TAB(PR,PC); " ";
       PC = 1
       PRINT TAB(PR,PC); "R";
       GOTO CHECK'END

MOVE'UP:
       CHAR = BOARD(PR-1)[PC;1]
       IF CHAR<>" " AND CHAR<>"o" AND CHAR<>"O" THEN GOTO GET'MOVE
       PRINT TAB(PR,PC); " ";
       PR = PR-1
       PRINT TAB(PR,PC); "U";
       BOARD(PR)[PC;1] = " "
       CALL RECORD'SCORE
       GOTO CHECK'END

MOVE'DOWN:
       CHAR = BOARD(PR+1)[PC;1]
       IF CHAR<>" " AND CHAR<>"o" AND CHAR<>"O" THEN GOTO GET'MOVE
       PRINT TAB(PR,PC); " ";
       PR = PR+1
       PRINT TAB(PR,PC); "D";
       BOARD(PR)[PC;1] = " "
       CALL RECORD'SCORE
       GOTO CHECK'END


MOVE'GHOST:
       CALL UPDATE'FRUIT

       IF GHOSTS=0 THEN GOTO GET'MOVE

       IF ALERT>0 THEN ALERT = ALERT-1 : IF ALERT=0 THEN CALL CANCEL'ALERT

       IF DELAY<>0 THEN DELAY = DELAY-1 : GOTO GET'MOVE
       DELAY = GHOST'DELAY

       GHOST = GHOST+1
       IF GHOST>4 THEN GHOST=1
       IF GR(GHOST)=0 THEN GOTO CREATE'GHOST                   ! dead ghost

       RETRIES = GHOST'RETRIES

       IF ALERT<>0 THEN GOTO GHOST'RANDOM

       IF GHOST=2 OR GHOST=4 THEN GOTO MGB

MGA:    IF PR<GR(GHOST) THEN GOTO GHOST'UP
       IF PR>GR(GHOST) THEN GOTO GHOST'DOWN
       IF PC<GC(GHOST) THEN GOTO GHOST'LEFT
       IF PC>GC(GHOST) THEN GOTO GHOST'RIGHT
       GOTO GHOST'RANDOM

MGB:    IF PC<GC(GHOST) THEN GOTO GHOST'LEFT
       IF PC>GC(GHOST) THEN GOTO GHOST'RIGHT
       IF PR<GR(GHOST) THEN GOTO GHOST'UP
       IF PR>GR(GHOST) THEN GOTO GHOST'DOWN

GHOST'RANDOM:
       DIR = INT(RND(0)*4)+1
       ON DIR GOTO GHOST'UP, GHOST'DOWN, GHOST'LEFT, GHOST'RIGHT

GHOST'DOWN:
       CHAR = BOARD(GR(GHOST)+1)[GC(GHOST);1]
       IF CHAR<>" " AND CHAR<>"o" AND CHAR<>"O" THEN GOTO GHOST'BLOCKED
       IF GR(GHOST)=9 AND GC(GHOST)=35 THEN &
               PRINT TAB(9,35); "!@#$%"[FRUIT'LEVEL;1]; :&
               GOTO GD1
       PRINT TAB(-1,11);
       PRINT TAB(GR(GHOST),GC(GHOST)); BOARD(GR(GHOST))[GC(GHOST);1];
       PRINT TAB(-1,12);
GD1:    GR(GHOST) = GR(GHOST)+1
       CALL BLINK'ON
       PRINT TAB(GR(GHOST),GC(GHOST)); "G";
       CALL BLINK'OFF
       GOTO CHECK'END

GHOST'UP:
       CHAR = BOARD(GR(GHOST)-1)[GC(GHOST);1]
       IF CHAR<>" " AND CHAR<>"o" AND CHAR<>"O" THEN GOTO GHOST'BLOCKED
       IF GR(GHOST)=9 AND GC(GHOST)=35 THEN &
               PRINT TAB(9,35); "!@#$%"[FRUIT'LEVEL;1]; :&
               GOTO GU1
       PRINT TAB(-1,11);
       PRINT TAB(GR(GHOST),GC(GHOST)); BOARD(GR(GHOST))[GC(GHOST);1];
       PRINT TAB(-1,12);
GU1:    GR(GHOST) = GR(GHOST)-1
       CALL BLINK'ON
       PRINT TAB(GR(GHOST),GC(GHOST)); "G";
       CALL BLINK'OFF
       GOTO CHECK'END

GHOST'LEFT:
       CHAR = BOARD(GR(GHOST))[GC(GHOST)-2;1]
       IF CHAR<>" " AND CHAR<>"o" AND CHAR<>"O" THEN GOTO GHOST'BLOCKED
       IF GR(GHOST)=9 AND GC(GHOST)=35 THEN &
               PRINT TAB(9,35); "!@#$%"[FRUIT'LEVEL;1]; :&
               GOTO GL1
       PRINT TAB(-1,11);
       PRINT TAB(GR(GHOST),GC(GHOST)); BOARD(GR(GHOST))[GC(GHOST);1];
       PRINT TAB(-1,12);
GL1:    GC(GHOST) = GC(GHOST)-2
       CALL BLINK'ON
       PRINT TAB(GR(GHOST),GC(GHOST)); "G";
       CALL BLINK'OFF
       GOTO CHECK'END

GHOST'RIGHT:
       CHAR = BOARD(GR(GHOST))[GC(GHOST)+2;1]
       IF CHAR<>" " AND CHAR<>"o" AND CHAR<>"O" THEN GOTO GHOST'BLOCKED
       IF GR(GHOST)=9 AND GC(GHOST)=35 THEN &
               PRINT TAB(9,35); "!@#$%"[FRUIT'LEVEL;1]; :&
               GOTO GR1
       PRINT TAB(-1,11);
       PRINT TAB(GR(GHOST),GC(GHOST)); BOARD(GR(GHOST))[GC(GHOST);1];
       PRINT TAB(-1,12);
GR1:    GC(GHOST) = GC(GHOST)+2
       CALL BLINK'ON
       PRINT TAB(GR(GHOST),GC(GHOST)); "G";
       CALL BLINK'OFF
       GOTO CHECK'END

GHOST'BLOCKED:
       IF RETRIES=0 THEN GOTO GET'MOVE
       RETRIES = RETRIES-1
       GOTO GHOST'RANDOM

CREATE'GHOST:
       GR(GHOST) = 9
       GC(GHOST) = 35
       GHOSTS = GHOSTS+1
       GOTO GET'MOVE

BLINK'ON:
       IF ALERT>0 THEN PRINT TAB(-1,108);
       RETURN

BLINK'OFF:
       IF ALERT>0 THEN PRINT TAB(-1,109);
       RETURN

CHECK'END:
       FLAG = 0
       IF FRUIT'FLAG<>0 AND PR=9 AND PC=35 THEN CALL GOT'FRUIT
       FOR I =1 TO 4
               IF GR(I)=PR AND GC(I)=PC THEN FLAG = I : I = 4
               NEXT I
       IF FLAG=0 THEN GOTO GET'MOVE
       IF ALERT<>0 THEN GOTO KILL'GHOST
       PRINT TAB(22,32); "LLL end game RRR";
       GOTO AGAIN

GOT'FRUIT:
       FRUIT'FLAG = 0
       FRUIT'DELAY = 0
       SCORE = SCORE+(FRUIT'LEVEL*1000)
       RETURN

KILL'GHOST:
       GR(FLAG) = 0 : GC(FLAG) = 0
       SCORE = SCORE+1000
       PRINT TAB(22,1); STR(SCORE);
       GHOSTS = GHOSTS-1
       GOTO GET'MOVE


UPDATE'FRUIT:
       IF FRUIT'FLAG THEN GOTO KILL'FRUIT

MAKE'FRUIT:
       IF SCORE<((FRUIT'LEVEL*3000)+1500) THEN RETURN
       FRUIT'FLAG = -1
       FRUIT'DELAY = 250
       FRUIT'LEVEL = FRUIT'LEVEL+1
       I = FRUIT'LEVEL
       IF I>5 THEN I = 1
       PRINT TAB(9,35); "!@#$%"[I;1];
       RETURN

KILL'FRUIT:
       FRUIT'DELAY = FRUIT'DELAY-1
       IF FRUIT'DELAY<>0 THEN RETURN
       FRUIT'FLAG = 0
       PRINT TAB(-1,11);
       PRINT TAB(9,35); BOARD(9)[35;1];
       PRINT TAB(-1,12);
       RETURN


AGAIN:  PRINT TAB(23,1); "play again? "; TAB(-1,28);
A1:     XCALL PAC65B, CHAR
       IF CHAR="" THEN GOTO A1
       PRINT TAB(-1,29);
       CHAR = UCS(CHAR)
       IF CHAR="N" OR CHAR=CHR(27) THEN GOTO EXIT
       IF CHAR="Y" THEN GOTO NEW'GAME
       GOTO A1
EXIT:   PRINT CHR(27); "~5"; TAB(-1,0); TAB(-1,12); TAB(-1,28);
       END


!*************
!*  NEWGAME  *
!*************

NEWGAME:
       PR = 11 : PC = 35                       ! PacMan row/column
       GR(1) = 7 : GC(1) = 35                  ! Ghost 1
       GR(2) = 9 : GC(2) = 33                  ! Ghost 2
       GR(3) = 9 : GC(3) = 35                  ! Ghost 3
       GR(4) = 9 : GC(4) = 37                  ! Ghost 4
       GHOSTS = 4
       ALERT = 0
       DOTS = 338
       FRUIT'FLAG = 0
       RETURN

!******************
!*  RECORD'SCORE  *
!******************

RECORD'SCORE:
       IF CHAR<>"o" AND CHAR<>"O" THEN RETURN
       DOTS = DOTS-1
       IF DOTS=0 THEN GOTO NEW'SCREEN
       IF CHAR="o" THEN SCORE = SCORE+100
       IF CHAR="O" THEN SCORE = SCORE+100
       IF CHAR="O" THEN ALERT = ALERT + (GHOST'DELAY*200) : CALL SET'ALERT
       PRINT TAB(22,1); STR(SCORE);
       RETURN

SET'ALERT:
       FOR I = 1 TO 4
               IF GR(I)=0 THEN GOTO SA1
               PRINT TAB(GR(I),GC(I)); TAB(-1,108); "G"; TAB(-1,109);
SA1:            NEXT I
       RETURN

CANCEL'ALERT:
       FOR I = 1 TO 4
               IF GR(I)=0 THEN GOTO CA1
               PRINT TAB(GR(I),GC(I)); "G";
CA1:            NEXT I
       RETURN

!***********
!*  INTRO  *
!***********

INTRO:  PRINT TAB(-1,0); TAB(-1,29);
       PRINT TAB(12,15); "o o o o o o o o o o   P a c   6 5   o o o o o o o o o ";
       PRINT TAB(12,1); "R";
       FOR I = 3 TO 79 STEP 2
               PRINT TAB(12,I); "R";
               PRINT TAB(12,I-2); " ";
               FOR J =1 TO 750 : NEXT J
               NEXT I
       PRINT TAB(12,79); " ";
       FOR I = 3 TO 79 STEP 2
               PRINT TAB(12,I); "G";
               PRINT TAB(12,I-2); " ";
               FOR J =1 TO 500 : NEXT J
               NEXT I
       PRINT TAB(12,79); " ";
       FOR J = 1 TO 1000 : NEXT J
       FOR I = 77 TO 3 STEP -1
               PRINT TAB(12,I); "G"; TAB(12,I+2); "L";
               IF I<77 THEN PRINT TAB(12,I+4); " ";
               FOR J = 1 TO 500 : NEXT J
               NEXT I
       FOR J = 1 TO 2000 : NEXT J
       RETURN

!****************
!*  BACKGROUND  *
!****************

BACKGROUND:
       PRINT TAB(-1,0); TAB(-1,29); TAB(-1,11);
       RESTORE
       I = 0
S1:     READ TEXT
       IF TEXT="END" THEN GOTO S2
       I = I+1
       BOARD(I) = TEXT
S1A:    POS = INSTR(1,TEXT,"#")
       IF POS=0 THEN GOTO S1B
       TEXT[POS;1] = " "
       GOTO S1A
S1B:    PRINT TEXT
       GOTO S1
S2:     PRINT TAB(-1,12);
       PRINT TAB(1,1); "Pac 65"; TAB(1,74); "game "; STR(GAME);
       RETURN


DATA ""
DATA "[-------------------------------------------------------------------]"
DATA "| O o o o o o o o o o o o o o o o o o o o o o o o o o o o o o o o O |"
DATA "| o [-----------------] o ----------------- o [-----------------] o |"
DATA "| o | o o o o o o o o | o o o o o o o o o o o | o o o o o o o o | o |"
DATA "| o o o [---------] o | o [---------------] o | o [---------] o o o |"
DATA "| o | o {---------} o | o | o o o o o o o | o | o {---------} o | o |"
DATA "| o | o o o o o o o o o o | o --------- o | o o o o o o o o o o | o |"
DATA "| o {-----------------] o o o o o o o o o o o [-----------------} o |"
DATA "} o o o o o o o o o o {-----------------------} o o o o o o o o o o {"
DATA "# o o o o o o o o o o o o o o o o o o o o o o o o o o o o o o o o o #"
DATA "] o ------------------------------------------------------------- o ["
DATA "| o o o o o o o o o o o o o o o o o o o o o o o o o o o o o o o o o |"
DATA "| o [-----------------] o [---------------] o [-----------------] o |"
DATA "| o | o o o o o o o o | o | o o o o o o o | o | o o o o o o o o | o |"
DATA "| o | o [---------] o | o | o o | o | o o | o | o [---------] o | o |"
DATA "| o | o {---------} o | o | o o | o | o o | o | o {---------} o | o |"
DATA "| o | o o o o o o o o o o | o o | o | o o | o o o o o o o o o o | o |"
DATA "| o {------------------ o {-----} o {-----} o ------------------} o |"
DATA "| O o o o o o o o o o o o o o o o o o o o o o o o o o o o o o o o O |"
DATA "{-------------------------------------------------------------------}"
DATA "END"