'===========================================================================
' Subject: PACMAN LIVES!                      Date: 07-18-96 (23:20)       
'  Author: Steven Hanov                       Code: QB, QBasic, PDS        
'  Origin: hanovs@wchat.on.ca               Packet: GAMES.ABC
'===========================================================================
'**************************************************************************
'**                         PACMAN LIVES!                                **
'****           By Steven Hanov (hanovs@wchat.on.ca)                     **
'**************************************************************************
'** July 1996                                                            **
'** Well, here's MY attempt at Pacman for QBASIC. I derived this game    **
'** from the Commodore 64 version, which was probably based on the Atari **
'** version. Quite a long history! I think it even had a cartoon show... **
'** On a 386, like mine :-(, a speed factor of zero should be used. The  **
'** graphics routines are slower than I'd have liked, but that's life.   **
'** If anyone manages to speed it up greatly, I'd appreciate a copy.     **
'** Just e-mail it to me.                                                **
'**************************************************************************

DECLARE SUB pacprint (y!, text$)
DECLARE SUB KillPac ()
DECLARE SUB DisplayLives (lives!)
DECLARE SUB UpdateScore ()
DECLARE SUB RedGhost ()
DECLARE SUB GreenGhost ()
DECLARE SUB BlueGhost ()
DECLARE SUB CreateGhost (colour!, frame!)
DECLARE SUB DrawPac (xx!, yy!, dr!)
DIM SHARED pf(-1 TO 81, 25) AS STRING, PacGraph(628)
DIM SHARED BGhost1(628), rGhost1(628), gGhost1(628), ZGhost1(628)
DIM SHARED BGhost2(628), rGhost2(628), GGhost2(628), ZGhost2(628)
DIM SHARED death, PowerUp, PTimer, xx, yy, Score, DontCallGhosts
DIM SHARED GameSpeed
'*********************************************************************
'** VARIABLE Dictionary **********************************************
'pf(x,y) contains the playing field, * for walls, . for dashes, o for powerup
'PacGraph, and the Ghosts store the "sprites" of pacman circle and ghosts
'death - Set by ghost sub to notify main that Pacman has been killed
'PowerUp - 1 if currently Powered Up, zero otherwise
'PTimer - The timer at the time Pacman got powerup.
'xx,yy - usually The current 320x200 screen position
'x,y - usually the current 40x25 screen position
'DontCallGhosts - Flag used to make DrawPac not call Ghosts
'GameSpeed - Slow down factor

rt$ = CHR$(0) + "M"     'define right, left, up, down keys
lt$ = CHR$(0) + "K"
up$ = CHR$(0) + "H"
dn$ = CHR$(0) + "P"
SCREEN 12
CIRCLE (150, 200), 150, 14
PAINT (150, 200), 14
LINE (150, 200)-(300, 160), 15
LINE -(300, 240), 15
LINE -(150, 200)
PAINT (160, 200), 0, 15             'The next several lines draw
LINE (150, 200)-(300, 160), 0      'the title screen...
LINE -(300, 240), 0
LINE -(150, 200), 0
CIRCLE (175, 125), 30, 0
PAINT (175, 125), 15, 0
CIRCLE (180, 130), 20, 0
PAINT (180, 130), 0, 0
CIRCLE (500, 150), 100, 4
PAINT (500, 150), 4
LINE (400, 150)-(400, 400), 4
LINE (600, 150)-(600, 400), 4
DRAW "BM600,400 H20 G20 H20 G20 H20 G20 H20 G20 H20 G20"
PAINT (500, 300), 4
CIRCLE (450, 150), 25, 0
CIRCLE (550, 150), 25, 0
PAINT (450, 150), 15, 0
PAINT (550, 150), 15, 0
CIRCLE (440, 150), 12, 0
CIRCLE (540, 150), 12, 0
PAINT (440, 150), 0
PAINT (540, 150), 0
CIRCLE (500, 225), 30, 0, , , .5
PAINT (500, 225), 0, 0
COLOR 9
x = 25
y = 0
LINE (x, y)-(x + 30, y + 100), 9, BF
CIRCLE (x + 35, y + 31), 30, 9
PAINT (x + 35, y + 31), 9, 9
CIRCLE (x + 35, y + 31), 2, 0
PAINT (x + 35, y + 31), 0, 0
x = x + 60
LINE (x + 40, y)-(x, y + 100)
LINE -(x + 80, y + 100)
LINE -(x + 40, y)
PAINT (x + 40, y + 50), 9, 9
CIRCLE (x + 40, y + 50), 2, 0
PAINT (x + 40, y + 50), 0, 0
x = x + 90
CIRCLE (x + 40, y + 50), 50
PAINT (x + 40, y + 50), 9, 9
LINE (x + 40, y + 50)-(x + 90, y + 20), 0
LINE -(x + 90, y + 80), 0
LINE -(x + 40, y + 50), 0
PAINT (x + 60, y + 50), 0, 0
x = x + 90
LINE (x + 10, y + 40)-(x + 40, y + 60), 9, BF
x = x + 50

LINE (x, y)-(x, y + 100), 9
LINE -(x + 90, y + 100), 9
LINE -(x + 90, y), 9
LINE -(x + 45, y + 50), 9
LINE -(x, y), 9
PAINT (x + 45, y + 75), 9, 9

x = x + 100
LINE (x + 40, y)-(x, y + 100)
LINE -(x + 80, y + 100)
LINE -(x + 40, y)
PAINT (x + 40, y + 50), 9, 9
CIRCLE (x + 40, y + 50), 2, 0
PAINT (x + 40, y + 50), 0, 0
x = x + 90
LINE (x, y)-(x, y + 100), 9
LINE -(x + 90, y + 100), 9
LINE -(x + 90, y), 9
LINE -(x + 60, y), 9
LINE -(x + 60, y + 50), 9
LINE -(x, y), 9
PAINT (x + 30, y + 30), 9, 9

COLOR 15
LOCATE 8, 36
PRINT "Lives!"
LOCATE 28, 20
COLOR 9
PRINT "Coded by Steven Hanov (hanovs@wchat.on.ca)"

WHILE INKEY$ = "": WEND
SCREEN 7                  'OK, now the real program begins!
RANDOMIZE TIMER
CLS
CIRCLE (12, 12), 5, 14
PAINT (12, 12), 14
GET (7, 7)-(17, 17), PacGraph
CreateGhost 9, 1             'Create and store "sprites"
GET (1, 0)-(11, 9), BGhost1
CreateGhost 9, 2
GET (1, 0)-(11, 9), BGhost2
CreateGhost 4, 1
GET (1, 0)-(11, 9), rGhost1
CreateGhost 4, 2
GET (1, 0)-(11, 9), rGhost2
CreateGhost 2, 1
GET (1, 0)-(11, 9), gGhost1
CreateGhost 2, 2
GET (1, 0)-(11, 9), GGhost2
CreateGhost 1, 1
GET (1, 0)-(11, 9), ZGhost1
CreateGhost 1, 2
GET (1, 0)-(11, 9), ZGhost2
CLS
pacprint 5, "Enter a delay factor, to"
pacprint 6, "slow down the game for"
pacprint 7, "fast computers. (0-15)"
LOCATE 9, 18: INPUT ">", a$
GameSpeed = VAL(a$) * 100
Start:
CLS
RESTORE
lives = 3
y = 0
xx = 0
yy = 0
DO
   READ a$                         'Read in, store, and display
   IF a$ = "STOP" THEN EXIT DO     'the playing field. (Stored in pf())
   yy = yy + 1
   FOR xx = 1 TO LEN(a$)
      y = yy * 8 - 8
      x = xx * 8 - 8
      B$ = MID$(a$, xx, 1)
      IF B$ = "." THEN
         LOCATE yy, xx + 1
         LINE (x + 3, y + 4)-(x + 5, y + 5), 14, B
         pf(xx, yy) = B$
         dots = dots + 1
      ELSEIF B$ = "o" THEN
         LOCATE yy, xx + 1
         CIRCLE (x + 4, y + 4), 3, 14
         PAINT (x + 4, y + 4), 14, 14
         pf(xx, yy) = B$
      ELSEIF B$ = " " THEN
         PRINT " ";
         pf(xx, yy) = " "
      ELSE
         COLOR 1             'For simplicity, all wall blocks are
         PRINT B$;           'stored in pf() array as "*"'s
         pf(xx, yy) = "*"
      END IF
   NEXT
   PRINT
LOOP
DO
     x = 20
     y = 18
     xx = x * 8 - 8
     yy = y * 8 - 8
     dr = 4
     DisplayLives lives
     PCOPY 0, 1
     DrawPac xx + 1, yy, 4
     DrawPac xx, yy, 4
     a$ = ""
     DO                             'This big DO-LOOP is the heart of the
     IF LEN(c$) = 0 THEN            'program, detecting keys and moving
          B$ = INKEY$               'pacman.
     ELSE
          B$ = c$
          c$ = ""
     END IF
     DrawPac xx, yy, dr
     IF LEN(B$) > 0 THEN
          IF B$ = CHR$(27) THEN CLS : GOTO Quit
          free = 0
          
          IF B$ = up$ AND pf(x, y - 1) <> "*" THEN free = free + 1
          IF B$ = rt$ AND pf(x + 1, y) <> "*" THEN free = free + 1
          IF B$ = dn$ AND pf(x, y + 1) <> "*" THEN free = free + 1
          IF B$ = lt$ AND pf(x - 1, y) <> "*" THEN free = free + 1
          IF free > 0 THEN
          a$ = B$
          c$ = ""
          END IF
     END IF
     IF a$ = rt$ AND pf(x + 1, y) <> "*" THEN
          dr = 2
          FOR s = 1 TO 8
               xx = xx + 1
               DrawPac xx, yy, dr
          NEXT
          x = x + 1
          IF x = 39 THEN x = 1: xx = 1: DrawPac xx, yy, dr
     ELSEIF a$ = lt$ AND pf(x - 1, y) <> "*" THEN
          dr = 4
          FOR s = 1 TO 8
               xx = xx - 1
               DrawPac xx, yy, dr
               IF xx = 1 THEN x = 40: xx = 39 * 8 - 8
          NEXT
          x = x - 1
     ELSEIF a$ = up$ AND pf(x, y - 1) <> "*" THEN
          dr = 1
          FOR s = 1 TO 8
               yy = yy - 1
               DrawPac xx, yy, dr
          NEXT
          y = y - 1
     ELSEIF a$ = dn$ AND pf(x, y + 1) <> "*" THEN
          dr = 3
          FOR s = 1 TO 8
               yy = yy + 1
               DrawPac xx, yy, dr
          NEXT
          y = y + 1
     END IF
     IF pf(x, y) = "." THEN
          Score = Score + 10
          pf(x, y) = " "
          dots = dots - 1
          SOUND 800, .25
          SOUND 900, .25
          UpdateScore
          IF dots = 0 THEN EXIT DO
     ELSEIF pf(x, y) = "o" THEN
          PowerUp = 1
          pf(x, y) = " "
          Score = Score + 100
          UpdateScore
          FOR s = 37 TO 4000 STEP 20
               SOUND s, .05
               SOUND s + 100, .05
               SOUND s + 200, .05
               SOUND s + 300, .05
          NEXT
          PTimer = TIMER
     END IF
     IF xx MOD 8 = 1 THEN xx = xx - 1
     IF death = 1 THEN KillPac: EXIT DO
     LOOP
     IF dots = 0 THEN EXIT DO
     lives = lives - 1
     DisplayLives lives
     death = 0
LOOP UNTIL lives = -1
CLS
COLOR 4
IF lives = -1 THEN
   pacprint 10, "You LOSE!"
ELSE
   pacprint 10, "You WIN!"
END IF
SLEEP 1

Quit:
COLOR 15
pacprint 15, "Final Score:" + STR$(Score)
COLOR 9
pacprint 20, "ENTER to play again, or ESC to exit"
DO
   a$ = INKEY$
LOOP UNTIL a$ = CHR$(27) OR a$ = CHR$(13)
IF a$ = CHR$(27) THEN SCREEN 0: COLOR 7: END
IF a$ = CHR$(13) THEN GOTO Start






'     1234567890123456789012345678901234567890
DATA "ÉÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍËÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍ»"
DATA "º..................º..................º"
DATA "º.ÚÄÄÄÄ¿.ÚÄÄÄÄÄÄÄ¿.º.ÚÄÄÄÄÄÄÄ¿.ÚÄÄÄÄ¿.º"
DATA "º.³    ³.³       ³.º.³       ³.³    ³.º"
DATA "ºoÀÄÄÄÄÙ.ÀÄÄÄÄÄÄÄÙ.º.ÀÄÄÄÄÄÄÄÙ.ÀÄÄÄÄÙoº"
DATA "º.....................................º"
DATA "º.ÍÍÍÍÍÍ.ÚÄ¿.ÍÍÍÍÍÍËÍÍÍÍÍÍ.ÚÄ¿.ÍÍÍÍÍÍ.º"
DATA "º........³ ³.......º.......³ ³........º"
DATA "ÈÍÍÍÍÍÍ».³ ÆÍÍÍÍÍÍ º ÍÍÍÍÍÍµ ³.ÉÍÍÍÍÍÍ¼"
DATA "       º.³ ³               ³ ³.º       "
DATA "ÍÍÍÍÍÍÍ¼.ÀÄÙ ÚÄÄÄÄÄ ÄÄÄÄÄ¿ ÀÄÙ.ÈÍÍÍÍÍÍÍ"
DATA " ..........  ³           ³  .......... "
DATA "ÍÍÍÍÍÍÍ».ÚÄ¿ ÀÄÄÄÄÄÄÄÄÄÄÄÙ ÚÄ¿.ÉÍÍÍÍÍÍÍ"
DATA "       º.³ ³               ³ ³.º       "
DATA "ÉÍÍÍÍÍÍ¼.ÀÄÙ ÍÍÍÍÍÍËÍÍÍÍÍÍ ÀÄÙ.ÈÍÍÍÍÍÍ»"
DATA "º..................º..................º"
DATA "º.ÍÍÍÍÍ».ÍÍÍÍÍÍÍÍÍ.º.ÍÍÍÍÍÍÍÍÍ.ÉÍÍÍÍÍ.º"
DATA "ºo.....º.......................º.....oº"
DATA "ÌÍÍÍÍÍ.º.ÚÄ¿.ÍÍÍÍÍÍËÍÍÍÍÍÍ.ÚÄ¿.º.ÍÍÍÍÍ¹"
DATA "º........³ ³.......º.......³ ³........º"
DATA "º.ÍÍÍÍÍÍÍÏÍÏÍÍÍÍÍÍ.º.ÍÍÍÍÍÍÏÍÏÍÍÍÍÍÍÍ.º"
DATA "º.....................................º"
DATA "ÈÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍ¼"


DATA STOP

'Takes care of blue ghost.
'And I mean it takes care of EVERYTHING:
'Drawing, artificial intelligence, killing Pacman, Killing itself...etc.
'
SUB BlueGhost

'VARIABLES:
'px,py - current pixel position
'PrevX,PrevY - previous pixel position (for erasing)
'flag - First time called?
'xdir, ydir - Which direction am I going in? (incremental values)

STATIC frame, PrevX, PrevY, flag, px, py, xdir, ydir
IF flag = 0 THEN
   flag = 1            'If first time called,
   PrevX = 17 * 8 - 8  'Set ghost to default position
   PrevY = 12 * 8 - 8
   px = PrevX
   py = PrevY
   xdir = 1    'Start off going right
   ydir = 0
END IF
IF PowerUp = 1 THEN
   speed = .5       'Powerup means half speed of ghosts
ELSE
   speed = 1
END IF

LINE (PrevX, PrevY)-(PrevX + 10, PrevY + 9), 0, BF 'ERase previous draw

IF px MOD 8 = 0 AND py MOD 8 = 0 THEN  'If you're centered on 8x8 box,
   x = (px \ 8) + 1      'Calculate real 40x25 screen position
   y = (py \ 8) + 1
   IF pf(x - xdir, y - ydir) = "." THEN     'Redraw the pellet you passed
         xp = CINT(px) - 8 * xdir           'over
         yp = CINT(py) - 8 * ydir
         LINE (xp + 3, yp + 4)-(xp + 5, yp + 5), 14, B
   ELSEIF pf(x - xdir, y - ydir) = "o" THEN   'redraw the powerup you passed
         xp = CINT(px) - 8 * xdir             'over
         yp = CINT(py) - 8 * ydir
         CIRCLE (xp + 4, yp + 4), 3, 14
         PAINT (xp + 4, yp + 4), 14, 14
   END IF
   IF pf(x, y + 1) <> "*" THEN free = free + 1   'Count the number of choices
   IF pf(x + 1, y) <> "*" THEN free = free + 1   'of directions without walls
   IF pf(x, y - 1) <> "*" THEN free = free + 1
   IF pf(x - 1, y) <> "*" THEN free = free + 1
   IF free > 2 OR pf(x + xdir, y + ydir) = "*" THEN 'IF you HAVE a choice,
      DO
         IF RND > .5 THEN
            xdir = 1
            ydir = 0         'Keep picking a random direction until
         ELSE                'you find one without a wall.
            ydir = 1
            xdir = 0
         END IF
         IF RND > .5 THEN xdir = -xdir: ydir = -ydir
         IF pf(x + xdir, y + ydir) <> "*" THEN EXIT DO
      LOOP
   END IF
END IF
px = px + xdir * speed          'Move the px,py co-ordinate
py = py + ydir * speed
IF px > 309 THEN px = 1      'Scroll from one side of screen to other
IF CINT(px) = 0 THEN px = 304
frame = frame + 1: IF frame = 2 THEN frame = 0 'Ghosts have two frames for
IF frame = 0 THEN                              'animation
   IF PowerUp = 1 THEN
      PUT (px, py), ZGhost1         'You have powerup, show scared ghost
   ELSE
      PUT (px, py), BGhost1       'Show regular ghost
   END IF
ELSE
   IF PowerUp = 1 THEN       'OR frame 2 of same.
      PUT (px, py), ZGhost2
   ELSE
      PUT (px, py), BGhost2
   END IF
END IF
PrevX = CINT(px)
PrevY = CINT(py)

   gx = (px \ 8) + 1
   gy = (py \ 8) + 1
   IF gx = xx \ 8 + 1 AND gy = yy \ 8 + 1 THEN  'If you hit Pacman,
      IF PowerUp = 1 THEN
         Score = Score + 200              'And he has powerup, kill ghost
         UpdateScore
         FOR s = 37 TO 5000 STEP 500
            SOUND s, 1
         NEXT
         flag = 0
      ELSE
         death = 1                     'OR else kill Pacman.
      END IF
   END IF


END SUB

SUB CreateGhost (colour, frame)
CLS
CIRCLE (6, 3), 5, colour, 0, 6.28, .5
LINE (1, 3)-(11, 8), colour, BF
PAINT (6, 2), colour, colour
CIRCLE (3, 3), 1, 15
CIRCLE (9, 3), 1, 15
PSET (3, 3), 15
PSET (9, 3), 15
SELECT CASE frame
     CASE 1
          DRAW "BM1,9 C" + STR$(colour) + " e1f1e1f1e1F1e1f1e1f1"
          PSET (4, 3), 0
          PSET (10, 3), 0
     CASE 2
          DRAW "BM1,8 C" + STR$(colour) + " f1e1f1e1f1e1f1e1f1e1"
          PSET (2, 3), 0
          PSET (8, 3), 0
END SELECT
IF colour = 1 THEN
   DRAW "BM2,7 C0 e1r1f1r1e1r1f1r1"
END IF
END SUB

SUB DisplayLives (lives)

x = 308
y = 187
LINE (x + 5, y - 5)-(x - 100, y + 5), 0, BF
FOR s = 1 TO lives
   GOSUB TinyPac
   x = x - 16
NEXT
EXIT SUB

TinyPac:
CIRCLE (x - 1, y), 4, 14
PAINT (x - 1, y), 14, 14
LINE (x, y)-(x - 5, y - 2), 0
LINE (x, y)-(x - 5, y + 2), 0
LINE -(x - 5, y - 2), 0
PAINT (x - 3, y), 0, 0
RETURN

END SUB

SUB DrawPac (xx, yy, dr)
STATIC a, PrevX, PrevY, flag, adir
FOR s = 1 TO GameSpeed: NEXT
IF flag = 0 THEN  'If first time called, set PrevX,Y to same as xx,yy
   adir = 1
   flag = 1
   PrevX = xx
   PrevY = yy
END IF
IF xx = 0 THEN xx = 1       'Solves mysterious problem.
IF PrevX <> xx OR PrevY <> yy THEN  'Don't redraw if standing still.
   a = a + adir                        '"a" value moves mouth
   IF a = 5 OR a = 0 THEN adir = -adir
   LINE (PrevX - 1, PrevY)-(PrevX + 10, PrevY + 8), 0, BF
   PUT (xx - 1, yy - 1), PacGraph
   SELECT CASE dr                   'dr is direction:1=up, clockwise.
   CASE 1
      LINE (xx + 4, yy + 5)-(xx + 4 - a, yy), 0
      LINE (xx + 4, yy + 5)-(xx + 4 + a, yy), 0
      LINE -(xx + 4 - a, yy), 0
      PAINT (xx + 4, yy + 1), 0, 0
  CASE 2
   LINE (xx + 3, yy + 4)-(xx + 9, yy + 4 - a), 0
   LINE (xx + 3, yy + 4)-(xx + 9, yy + 4 + a), 0
   LINE -(xx + 9, yy + 4 - a), 0
   PAINT (xx + 7, yy + 4), 0, 0
  CASE 3
   LINE (xx + 4, yy + 3)-(xx + 4 - a, yy + 8), 0
   LINE (xx + 4, yy + 3)-(xx + 4 + a, yy + 8), 0
   LINE -(xx + 4 - a, yy + 8), 0
   PAINT (xx + 4, yy + 7), 0, 0
  CASE 4
   LINE (xx + 5, yy + 4)-(xx - 1, yy + 4 - a), 0
   LINE (xx + 5, yy + 4)-(xx - 1, yy + 4 + a), 0
   LINE -(xx - 1, yy + 4 - a), 0
   PAINT (xx, yy + 4), 0, 0
  END SELECT
END IF
PrevX = xx
PrevY = yy

IF TIMER - PTimer > 10 THEN PowerUp = 0  'Powerup lasts 10 seconds
IF DontCallGhosts = 0 THEN
   RedGhost
   GreenGhost     'Move the three ghosts
   BlueGhost
END IF
END SUB

'For comments, see BlueGhost sub
SUB GreenGhost
STATIC frame, PrevX, PrevY, flag, px, py, xdir, ydir
IF flag = 0 THEN
   flag = 1
   PrevX = 17 * 8 - 8
   PrevY = 12 * 8 - 8
   px = PrevX
   py = PrevY
   xdir = 1
   ydir = 0
END IF
IF PowerUp = 1 THEN
   speed = .5
ELSE
   speed = 1
END IF

LINE (PrevX, PrevY)-(PrevX + 10, PrevY + 9), 0, BF

IF px MOD 8 = 0 AND py MOD 8 = 0 THEN
   x = (px \ 8) + 1
   y = (py \ 8) + 1
   IF pf(x - xdir, y - ydir) = "." THEN
         xp = CINT(px) - 8 * xdir
         yp = CINT(py) - 8 * ydir
         LINE (xp + 3, yp + 4)-(xp + 5, yp + 5), 14, B
   ELSEIF pf(x - xdir, y - ydir) = "o" THEN
         xp = CINT(px) - 8 * xdir
         yp = CINT(py) - 8 * ydir
         CIRCLE (xp + 4, yp + 4), 3, 14
         PAINT (xp + 4, yp + 4), 14, 14
   END IF
   IF pf(x, y + 1) <> "*" THEN free = free + 1
   IF pf(x + 1, y) <> "*" THEN free = free + 1
   IF pf(x, y - 1) <> "*" THEN free = free + 1
   IF pf(x - 1, y) <> "*" THEN free = free + 1
   IF free > 2 OR pf(x + xdir, y + ydir) = "*" THEN
      DO
         IF RND > .5 THEN
            xdir = 1
            ydir = 0
         ELSE
            ydir = 1
            xdir = 0
         END IF
         IF RND > .5 THEN xdir = -xdir: ydir = -ydir
         IF pf(x + xdir, y + ydir) <> "*" THEN EXIT DO
      LOOP
   END IF
END IF
px = px + xdir * speed
py = py + ydir * speed
IF px > 309 THEN px = 1
IF CINT(px) = 0 THEN px = 304
frame = frame + 1: IF frame = 2 THEN frame = 0
IF frame = 0 THEN
   IF PowerUp = 1 THEN
      PUT (px, py), ZGhost1
   ELSE
      PUT (px, py), gGhost1
   END IF
ELSE
   IF PowerUp = 1 THEN
      PUT (px, py), ZGhost2
   ELSE
      PUT (px, py), GGhost2
   END IF
END IF
PrevX = CINT(px)
PrevY = CINT(py)

   gx = (px \ 8) + 1
   gy = (py \ 8) + 1
   IF gx = xx \ 8 + 1 AND gy = yy \ 8 + 1 THEN
      IF PowerUp = 1 THEN
         Score = Score + 200
         UpdateScore
         FOR s = 37 TO 5000 STEP 500
            SOUND s, 1
         NEXT
         flag = 0
      ELSE
         death = 1
      END IF
   END IF
END SUB

'Makes Pacman eat himself.
'
SUB KillPac
LINE (xx - 1, yy)-(xx + 10, yy + 8), 0, BF 'Blank out background
PUT (xx - 1, yy - 1), PacGraph      'Put the PacCircle there
freq = 1500 'Sound values
freq2 = 500
FOR y = -5 TO 5 STEP .2
      LINE (xx + 4, yy + 5)-(xx + 4 + SQR(25 - y ^ 2), yy + 5 + y), 0
      LINE (xx + 4, yy + 5)-(xx + 4 - SQR(25 - y ^ 2), yy + 5 + y), 0
               '^ Wow! I actually found a use for grade 12 math!
      SOUND freq, .5
      SOUND freq2, .5
      freq = freq - 10
      freq2 = freq2 + 10
NEXT
END SUB

SUB pacprint (y, text$)
DontCallGhosts = 1
yy = y * 8 - 8
x = 20 - LEN(text$) \ 2
xx = x * 8 - 7
FOR letter = 1 TO LEN(text$)
   FOR xx = xx TO xx + 7
      DrawPac xx, yy, 2
   NEXT
   LOCATE y, x
   x = x + 1
   PRINT MID$(text$, letter, 1)
   SOUND 800, .25
   SOUND 900, .25
NEXT
DontCallGhosts = 0
END SUB

'For comments, see BlueGhost sub
SUB RedGhost
STATIC frame, PrevX, PrevY, flag, px, py, xdir, ydir
IF flag = 0 THEN
   flag = 1
   PrevX = 17 * 8 - 8
   PrevY = 12 * 8 - 8
   px = PrevX
   py = PrevY
   xdir = 1
   ydir = 0
END IF
IF PowerUp = 1 THEN
   speed = .5
ELSE
   speed = 1
END IF

LINE (PrevX, PrevY)-(PrevX + 10, PrevY + 9), 0, BF

IF px MOD 8 = 0 AND py MOD 8 = 0 THEN
   x = (px \ 8) + 1
   y = (py \ 8) + 1
   IF pf(x - xdir, y - ydir) = "." THEN
         xp = CINT(px) - 8 * xdir
         yp = CINT(py) - 8 * ydir
         LINE (xp + 3, yp + 4)-(xp + 5, yp + 5), 14, B
   ELSEIF pf(x - xdir, y - ydir) = "o" THEN
         xp = CINT(px) - 8 * xdir
         yp = CINT(py) - 8 * ydir
         CIRCLE (xp + 4, yp + 4), 3, 14
         PAINT (xp + 4, yp + 4), 14, 14
   END IF
   IF pf(x, y + 1) <> "*" THEN free = free + 1
   IF pf(x + 1, y) <> "*" THEN free = free + 1
   IF pf(x, y - 1) <> "*" THEN free = free + 1
   IF pf(x - 1, y) <> "*" THEN free = free + 1
   IF free > 2 OR pf(x + xdir, y + ydir) = "*" THEN
      DO
         IF RND > .5 THEN
            xdir = 1
            ydir = 0
         ELSE
            ydir = 1
            xdir = 0
         END IF
         IF RND > .5 THEN xdir = -xdir: ydir = -ydir
         IF pf(x + xdir, y + ydir) <> "*" THEN EXIT DO
      LOOP
   END IF
END IF
px = px + xdir * speed
py = py + ydir * speed
IF px > 309 THEN px = 1
IF CINT(px) = 0 THEN px = 304
frame = frame + 1: IF frame = 2 THEN frame = 0
IF frame = 1 THEN
   IF PowerUp = 1 THEN
      PUT (px, py), ZGhost1
   ELSE
      PUT (px, py), rGhost1
   END IF
ELSE
   IF PowerUp = 1 THEN
      PUT (px, py), ZGhost2
   ELSE
      PUT (px, py), rGhost2
   END IF
END IF
PrevX = CINT(px)
PrevY = CINT(py)

   gx = (px \ 8) + 1
   gy = (py \ 8) + 1
   IF gx = xx \ 8 + 1 AND gy = yy \ 8 + 1 THEN
      IF PowerUp = 1 THEN
         Score = Score + 200
         UpdateScore
         FOR s = 37 TO 5000 STEP 500
            SOUND s, 1
         NEXT
         flag = 0
      ELSE
         death = 1
      END IF
   END IF
END SUB

SUB UpdateScore
LOCATE 24, 1
COLOR 15
PRINT Score;
END SUB

