REM Original Liberty BASIC version by Tom Watson (c) 1998 All Rights Reserved
      REM Adapted and simplified for BBC BASIC for Windows by Richard Russell, 2014
      LEFT = 1
      UP = 2
      RIGHT = 3
      DOWN = 4
      DIM gx(3),gy(3),gd(3),ga(3)
      lives = 3
      dead = 0
      done = 0
      bonus = 0
      ghostflash = 0
      ghostblue = 0
      fruit = 0
      dotcount = 0
      pacspeed = 5
      ghostspeed = 5
      slowghost = 1
      frame = 0
      dir = 1
      try = 0
      cx = 210
      cy = 240
      INPUT "Enter level (1-8): " level
      VDU 23,22,482;400;8,16,16,0
      VDU 24,0;-240;1918;798;
      VDU 28,0,1,59,0,5
      COLOUR 1,247,222,115
      *TEMPO 1
      PROCload
      PROCdrawlives
      REPEAT
        WAIT 10
        CASE INKEY(0) OF
          WHEN 136: newdir = 1 : try = TRUE
          WHEN 139: newdir = 2 : try = TRUE
          WHEN 137: newdir = 3 : try = TRUE
          WHEN 138: newdir = 4 : try = TRUE
        ENDCASE
        PROCdot
        PROCmovePacman
        PROCbackground
        PROCghost(0)
        PROCghost(1)
        PROCghost(2)
        PROCghost(3)
        PROCdetectGhost
        PROCdrawPacman
        IF dotcount = 254 THEN dotcount = 0 : PROCwin
        IF dead = 1 THEN dead = 0 : PROCdie
        IF done = 1 THEN PROCgameover
      UNTIL FALSE
      DEF PROCdrawlives
      LOCAL i
      GCOL 0 : RECTANGLE FILL 0,0,300,60
      IF lives<=1 ENDPROC
      FOR i = 1 TO lives-1
        RECTANGLE 960,6,56,56 TO i*60-60,10
      NEXT i
      ENDPROC
      DEF PROCdootFruit
      LOCAL sc$
      IF fruit = 1 IF cy = 180 IF cx > 220 IF cx < 230 THEN
        fruit = 0
        start = TIME
        CASE level OF
          WHEN 1: sc$ = "100"
          WHEN 2: sc$ = "200"
          WHEN 3: sc$ = "500"
          WHEN 4: sc$ = "700"
          WHEN 5: sc$ = "1000"
          WHEN 6: sc$ = "2000"
          WHEN 7: sc$ = "3000"
          OTHERWISE: sc$ = "5000"
        ENDCASE
        score += VAL(sc$)
        GCOL 15 : MOVE 500,362 : PRINT ;sc$;
        ENVELOPE 1,1,0,0,0,0,0,0,126,-1,0,-8,126,0
        SOUND 0,1,4,50
        WAIT 50
        PROCprintScore
      ENDIF
      ENDPROC
      DEF PROCmovePacman
      LOCAL i
      IF (ghostblue > 0) AND (TIME > ghostblue + (100 * (20 - (level * 2)))) THEN
        ghostblue = 0
        ghostflash = 0
        FOR i = 0 TO 3
          gx(i) -= gx(i) MOD 30 : gy(i) -= gy(i) MOD 30 : ga(i) = 1
        NEXT
      ENDIF
      IF TIME > ghostblue + 100 * (16 - (level * 2)) THEN ghostflash = NOT ghostflash
      PROCdootFruit
      IF try IF (cx MOD 15) = 0 IF (cy MOD 15) = 0 THEN
        CASE newdir OF
          WHEN 1: IF TINT(2*cx,   702-2*cy)<>blue dir = newdir : try = 0
          WHEN 4: IF TINT(2*cx+32,672-2*cy)<>blue dir = newdir : try = 0
          WHEN 3: IF TINT(2*cx+58,702-2*cy)<>blue dir = newdir : try = 0
          WHEN 2: IF TINT(2*cx+32,730-2*cy)<>blue dir = newdir : try = 0
        ENDCASE
      ENDIF
      CASE dir OF
        WHEN 1: IF TINT(2*cx,   702-2*cy)<>blue cx -= pacspeed ELSE cx = 30 * INT(cx/30 + 0.5) : frame = 2
        WHEN 4: IF TINT(2*cx+32,672-2*cy)<>blue cy += pacspeed ELSE cy = 30 * INT(cy/30 + 0.5) : frame = 2
        WHEN 3: IF TINT(2*cx+58,702-2*cy)<>blue cx += pacspeed ELSE cx = 30 * INT(cx/30 + 0.5) : frame = 2
        WHEN 2: IF TINT(2*cx+32,730-2*cy)<>blue cy -= pacspeed ELSE cy = 30 * INT(cy/30 + 0.5) : frame = 2
      ENDCASE
      IF cx<30 cx += 480
      IF cx>=460 cx -= 480
      ENDPROC
      DEF PROCdetectGhost
      LOCAL p,x,y,active,text$
      FOR p = 0 TO 3
        x = gx(p) : y = gy(p) : active = ga(p)
        IF ABS(cx-x) < 16 IF ABS(cy-y) < 16 THEN
          IF active = 0 THEN
            active = 1
            ghostcount += 1
            y += 25
            CASE ghostcount OF
              WHEN 1: text$ = "200"
              WHEN 2: text$ = "400"
              WHEN 3: text$ = "800"
              WHEN 4: text$ = "1600"
            ENDCASE
            score += VAL(text$)
            PROCprintScore
            GCOL 15 : MOVE x*2+32,712-y*2 : PRINT text$;
            ENVELOPE 1,1,0,0,0,0,0,0,126,-1,0,-8,126,0
            SOUND 0,1,4,50
            WAIT 50
            x = 225
            y = 150
          ELSE
            dead = 1
            ENDPROC
          ENDIF
        ENDIF
        ga(p) = active : gx(p) = x : gy(p) = y
      NEXT p
      ENDPROC
      DEF PROCbackground
      RECTANGLE 960,70,960,660 TO 0,70
      IF (TIME > start + 800) AND (TIME < start + 800 + (1000 - (50 * level))) THEN PROCdrawFruit : fruit = 1
      IF TIME >= start + 800 + (1000 - (50 * level)) THEN fruit = 0 : start = TIME
      ENDPROC
      DEF PROCdot
      IF (cx MOD 15) = 0 IF (cy MOD 15) = 0 THEN
        CASE TINT(992+2*cx,702-2*cy) OF
          WHEN yellow: PROCchomp : GCOL 0 : RECTANGLE FILL 976+2*cx,686-2*cy,32,32
          WHEN pink:   PROCpill  : GCOL 0 : RECTANGLE FILL 976+2*cx,686-2*cy,32,32
        ENDCASE
      ENDIF
      ENDPROC
      DEF PROCdrawFruit
      CASE level OF
        WHEN 1: RECTANGLE 1324,-52,48,48 TO 450,318
        WHEN 2: RECTANGLE 1384,-52,48,48 TO 450,318
        WHEN 3: RECTANGLE 1444,-52,48,48 TO 450,318
        WHEN 4: RECTANGLE 1204,-112,48,48 TO 450,318
        WHEN 5: RECTANGLE 1264,-112,48,48 TO 450,318
        WHEN 6: RECTANGLE 1324,-112,48,48 TO 450,318
        WHEN 7: RECTANGLE 1384,-112,48,48 TO 450,318
        WHEN 8: RECTANGLE 1444,-112,48,48 TO 450,318
      ENDCASE
      ENDPROC
      DEF PROCghost(i)
      LOCAL gx,gy,op,change
      op = TIME MOD 10
      IF gx(i) MOD 30 = 0 IF gy(i) MOD 30 = 0 IF op < 4 THEN gd(i) = op + 1
      IF ga(i) speed = ghostspeed ELSE speed = slowghost
      REPEAT
        change = FALSE
        CASE gd(i) OF
          WHEN 1: IF TINT(2*gx(i),   702-2*gy(i))=blue change = TRUE
          WHEN 4: IF TINT(2*gx(i)+32,672-2*gy(i))=blue change = TRUE
          WHEN 3: IF TINT(2*gx(i)+58,702-2*gy(i))=blue change = TRUE
          WHEN 2: IF TINT(2*gx(i)+32,730-2*gy(i))=blue change = TRUE
        ENDCASE
        IF change gd(i) = RND(4) : gx(i) = 30 * INT(gx(i)/30 + 0.5) : gy(i) = 30 * INT(gy(i)/30 + 0.5)
      UNTIL NOT change
      CASE gd(i) OF
        WHEN 1: gx(i) -= speed
        WHEN 4: gy(i) += speed
        WHEN 3: gx(i) += speed
        WHEN 2: gy(i) -= speed
      ENDCASE
      IF gx(i) < 0 THEN gx(i) = 450
      IF gx(i) > 450 THEN gx(i) = 0
      gy = 60*i
      CASE gd(i) OF
        WHEN LEFT:  gx = 0
        WHEN DOWN:  gx = 30
        WHEN RIGHT: gx = 60
        WHEN UP:    gx = 90
      ENDCASE
      IF ga(i) = 0 AND ghostflash = 0  THEN gx = 120 : gy = 0
      IF ga(i) = 0 AND ghostflash <> 0 THEN gx = 150 : gy = 0
      RECTANGLE gx*2+968,-50-gy,40,40 TO gx(i)*2+10,680-gy(i)*2
      ENDPROC
      DEF PROCdrawPacman
      LOCAL pacx
      frame = (frame + 1) MOD 3
      pacx = frame * 60 + 6
      CASE dir OF
        WHEN 4: pacx += 120
        WHEN 3: pacx += 240
        WHEN 2: pacx += 360
      ENDCASE
      IF frame = 2 pacx = 486
      RECTANGLE pacx+960,10,36,36 TO cx*2+8,680-cy*2
      ENDPROC
      DEF PROCload
      IF level > 8 THEN level = 8
      ga() = 1
      gx() = 240,240,180,270
      gy() = 120,150,150,150
      gd() = 1,2,3,1
      IF level < 6 THEN pacspeed = 5 : ghostspeed = 5 : slowghost = 1
      IF level > 5 THEN pacspeed = 15 : ghostspeed = 15 : slowghost = 5
      *DISPLAY pacmaze 960,-238
      blue = TINT(962,728)
      yellow = TINT(990,700)
      pink = TINT(990,640)
      RECTANGLE 1320,-56,56,56 TO 900,8
      IF level > 1 RECTANGLE 1380,-56,56,56 TO 840,8
      IF level > 2 RECTANGLE 1440,-56,56,56 TO 780,8
      IF level > 3 RECTANGLE 1200,-116,56,56 TO 720,8
      IF level > 4 RECTANGLE 1260,-116,56,56 TO 660,8
      IF level > 5 RECTANGLE 1320,-116,56,56 TO 600,8
      IF level > 6 RECTANGLE 1380,-116,56,56 TO 540,8
      IF level > 7 RECTANGLE 1440,-116,56,56 TO 480,8
      start = TIME
      ENDPROC
      DEF PROCchomp
      SOUND 1,-10,124,2
      score += 10
      dotcount += 1
      PROCprintScore
      ENDPROC
      DEF PROCpill
      ENVELOPE 1,1,1,-1,0,20,20,0,8,0,0,-6,126,0
      SOUND 1,1,20,40
      ghostcount = 0
      ga() = 0
      ghostblue = TIME
      ghostflash = 0
      score += 50
      dotcount += 1
      PROCprintScore
      ENDPROC
      DEF PROCprintScore
      MOVE 40,780 : GCOL 1 : CLS : PRINT "SCORE: "; score
      WHILE score >= (bonus+1) * 10000 AND (lives <= 6)
        lives += 1 : bonus += 1
      ENDWHILE
      PROCdrawlives
      ENDPROC
      DEF PROCwin
      LOCAL p
      fruit = 0
      level += 1
      dotcount = 0
      frame = 0
      dir = LEFT
      cx = 210
      cy = 240
      ENVELOPE 1,1,0,0,0,0,0,0,100,-4,0,-2,126,0
      SOUND 2,0,0,6
      FOR p = 24 TO 42
        SOUND (p MOD 2) + 1,1,p*4,12
        SOUND 3,1,216,6
      NEXT
      REPEAT WAIT 1 : UNTIL ADVAL(-6)=16
      PROCload
      PROCprintScore
      ENDPROC
      DEF PROCdie
      LOCAL p
      lives -= 1
      IF lives = 0 THEN done = 1
      PROCdrawlives
      ga() = 1
      gx() = 240,240,180,270
      gy() = 120,150,150,150
      gd() = LEFT,UP,RIGHT,LEFT
      ghostflash = 0
      ghostblue = 0
      fruit = 0
      frame = 0
      dir = 1
      RECTANGLE 1506,10,36,36 TO cx*2+8,680-cy*2
      cx = 210
      cy = 240
      ENVELOPE 1,1,0,0,0,0,0,0,100,-4,0,-100,126,0
      SOUND 2,0,0,12
      SOUND 3,0,0,6
      FOR p = 51 TO 24 STEP -1
        SOUND (p MOD 3) + 1,1,p*4,18
      NEXT
      REPEAT WAIT 1 : UNTIL ADVAL(-6)=16
      ENDPROC
      DEF PROCgameover
      *FONT Arial,80
      GCOL 15 : MOVE 0,600 : PRINT "   GAME"'"   OVER";
      REPEAT WAIT 1 : UNTIL FALSE