rem #####################################################
rem #     Program : Paccy
rem # 
rem #      Author : Marc Gale
rem #
rem # Description : A game that is extremely similar
rem #               to one of the all time arcade greats.
rem #
rem #####################################################

gosub initialise
gosub main_loop
exit

rem #####################################################
rem # Procedure name : main_loop
rem # 
rem #        Details : The main housekeeping routine.
rem #                  This is basically the heart of
rem #                  the program, calling routines 
rem #                  to do the various tasks required
rem #                  by the program.
rem #
rem #####################################################
label main_loop
 joypad=0
 repeat
  gosub title_screen
  gosub main_menu
 until (1=2)
return

rem #####################################################
rem # Procedure name : instructions
rem # 
rem #        Details : Displays the instructions
rem #####################################################
label instructions
  setdispbuf curbuf
  setdrawbuf curbuf

  clear window

  setrgb 1,0,0,100
  setrgb 2,0,0,0
  setrgb 3,0,0,100
  gtriangle 0,0 to 0,sh to sw,0
  setrgb 1,0,0,0
  gtriangle 0,sh to sw,sh to sw,0 

  setrgb 1,255,255,255
  line 50,60 to 600,60

  gosub waitfornoinput

  setrgb 1,200,100,200
  text 50,50,"Paccy - Copyright Marc Gale (Xalthorn) 2001","lb"

  setrgb 1,150,150,255
  for a=1 to instructlines
    if in$(a)<>"" then
      for b=1 to len(in$(a))
        text b*12+50,a*18+70,mid$(in$(a),b,1)
        buttons=or(peek("port1"),peek("port2"))
        if buttons=0 then
          wait 0.1
        fi
      next b
    fi
  next a

  gosub waitfornoinput

  setrgb 1,255,255,255
  text sw/2,sh-20,"Press the X button for the main menu","cc"

  repeat
    joypad=or(peek("port1"),peek("port2"))
  until (and(joypad,16384)=16384)
return

rem #####################################################
rem # Procedure name : cycle_back
rem # 
rem #        Details : Draw a cycling background
rem #
rem #####################################################
label cycle_back
 setrgb 1,0,0,colval
 setrgb 2,0,0,colval
 setrgb 3,0,0,255-colval
 gtriangle 0,0 to sw,0 to sw,sh
 setrgb 2,0,0,255-colval
 gtriangle 0,0 to sw,sh to 0,sh

 colval=colval+coldir
 if colval=0 or colval=255 then
  coldir=-coldir
 fi
return

rem #####################################################
rem # Procedure name : title_screen
rem # 
rem #        Details : The game housekeeping routine.
rem #
rem #####################################################
label title_screen
 m$=ti$
 mx=10
 mpos=0
 colval=0
 coldir=1
 xpos=0:ypos=0
 angle=0
 mouth=0
 mouthdir=1
 oldjoypad=joypad
 cont=0

 repeat
  gosub flip_screen
  gosub cycle_back

  angle=angle+1
  if angle>360 then
   angle=angle-360
  fi

  xpos=200+sines(angle)*200:ypos=220-cosines(angle)*220
  gosub write_title

  setrgb 1,colval,colval,colval
  text 250,250,"Press any key"

  gosub display_scroller

  joypad=peek("port1")
  if joypad<>oldjoypad and joypad>0 then
   cont=1
  fi
  if joypad<>oldjoypad then
   oldjoypad=joypad
  fi
 until (cont=1)
return

rem #####################################################
rem # Procedure name : write_title
rem # 
rem #        Details : draw the game title.  xpos and 
rem #                  ypos need to be set before this
rem #                  routine is called.
rem #
rem #####################################################
label write_title
  mouth=mouth+mouthdir
  if mouth=0 or mouth=20 then
   mouthdir=-mouthdir
  fi

  setrgb 1,255,255,255

  rem P
  fill rectangle xpos,ypos to xpos+10,ypos+40
  fill rectangle xpos+10,ypos to xpos+20,ypos+10
  fill rectangle xpos+10,ypos+20 to xpos+20,ypos+30
  fill rectangle xpos+20,ypos+10 to xpos+30,ypos+20
  fill triangle xpos+20,ypos to xpos+30,ypos+10 to xpos+20,ypos+10
  fill triangle xpos+20,ypos+20 to xpos+30,ypos+20 to xpos+20,ypos+30

  rem A
  xpos=xpos+50
  fill triangle xpos,ypos+40 to xpos+10,ypos to xpos+10,ypos+40
  fill rectangle xpos+10,ypos to xpos+30,ypos+10
  fill triangle xpos+30,ypos to xpos+30,ypos+40 to xpos+40,ypos+40
  fill rectangle xpos+10,ypos+20 to xpos+30,ypos+30
  fill triangle xpos+10,ypos+40 to xpos+15,ypos+30 to xpos+10,ypos+30
  fill triangle xpos+25,ypos+30 to xpos+30,ypos+30 to xpos+30,ypos+40
  fill triangle xpos+15,ypos+10 to xpos+15,ypos+20 to xpos+20,ypos+10
  fill triangle xpos+20,ypos+10 to xpos+25,ypos+10 to xpos+25,ypos+20
  fill rectangle xpos+10,ypos+10 to xpos+15,ypos+20
  fill rectangle xpos+25,ypos+10 to xpos+30,ypos+20

  setrgb 1,255,255,0
  xpos=xpos+50
  rem C
  fill triangle xpos,ypos+20 to xpos+20,ypos+20 to xpos+20,ypos
  fill triangle xpos+20,ypos to xpos+40,ypos+mouth to xpos+20,ypos+20
  fill triangle xpos,ypos+20 to xpos+20,ypos+20 to xpos+20,ypos+40
  fill triangle xpos+20,ypos+20 to xpos+20,ypos+40 to xpos+40,ypos+40-mouth

  xpos=xpos+50
  rem C
  fill triangle xpos,ypos+20 to xpos+20,ypos+20 to xpos+20,ypos
  fill triangle xpos+20,ypos to xpos+40,ypos+mouth to xpos+20,ypos+20
  fill triangle xpos,ypos+20 to xpos+20,ypos+20 to xpos+20,ypos+40
  fill triangle xpos+20,ypos+20 to xpos+20,ypos+40 to xpos+40,ypos+40-mouth

  setrgb 1,255,255,255
  xpos=xpos+50
  rem Y
  fill triangle xpos,ypos to xpos+10,ypos to xpos+10,ypos+20
  fill triangle xpos+10,ypos to xpos+20,ypos+10 to xpos+10,ypos+20
  fill triangle xpos,ypos+40 to xpos+10,ypos+40 to xpos+10,ypos+20
  fill triangle xpos+10,ypos+40 to xpos+10,ypos+20 to xpos+30,ypos
  fill triangle xpos+10,ypos+40 to xpos+30,ypos to xpos+40,ypos
return

rem #####################################################
rem # Procedure name : init_main_menu
rem # 
rem #        Details : reset the main variables of the
rem #                  main menu
rem #
rem #####################################################
label init_main_menu
 m$=me$
 mx=10
 mpos=0
 colval=0
 coldir=1
 mouth=0
 mouthdir=1
 option=0
 numoptions=3
 oldjoypad=joypad
return

rem #####################################################
rem # Procedure name : main_menu
rem # 
rem #        Details : The main menu
rem #
rem #####################################################
label main_menu
 gosub init_main_menu
 curpos=3

 repeat
  gosub flip_screen
  gosub cycle_back

  xpos=200:ypos=20
  gosub write_title

  gosub draw_main_menu

  gosub display_scroller

  joypad=peek("port1")
  if oldjoypad<>joypad then
   if and(joypad,64)>0 and curpos<numoptions then
    curpos=curpos+1
   fi

   if and(joypad,16)>0 and curpos>1 then
    curpos=curpos-1
   fi

   if and(joypad,16384)>0 then
    option=curpos
   fi
   oldjoypad=joypad
  fi

  if option=1 then
   gosub game_loop
   gosub init_main_menu
  fi

  if option=2 then
   gosub instructions
   gosub init_main_menu
  fi

 until (option=numoptions)
return

rem #####################################################
rem # Procedure name : waitfornoinput
rem # 
rem #        Details : Wait until nothing is being
rem #                  pressed
rem #
rem #####################################################
label waitfornoinput
 repeat
  joypad=or(peek("port1"),peek("port2"))
 until (joypad=0)
return

rem #####################################################
rem # Procedure name : draw_main_menu
rem # 
rem #        Details : Draw the main menu
rem #
rem #####################################################
label draw_main_menu
 setrgb 1,255,colval,0
 setrgb 2,255,colval,0
 setrgb 3,255,255-colval,0
 ypos=curpos*50+85
 gtriangle 220,ypos to 220,ypos+25 to 410,ypos
 setrgb 2,255,255-colval,0
 gtriangle 220,ypos+25 to 410,ypos to 410,ypos+25

 if curpos=1 then
  setrgb 1,0,0,0
 else
  setrgb 1,255,255,255
 fi
 text 270,150,"Start Game"

 if curpos=2 then
  setrgb 1,0,0,0
 else
  setrgb 1,255,255,255
 fi
 text 260,200,"Instructions"

 if curpos=3 then
  setrgb 1,0,0,0
 else
  setrgb 1,255,255,255
 fi
 text 240,250,"Return to title"
return

rem #####################################################
rem # Procedure name : flip_screen
rem # 
rem #        Details : This is the screen buffer handling
rem #                  routine.  Call this routine just
rem #                  before you start drawing your 
rem #                  screen.  Oh, you might want to 
rem #                  clear the window just after you've
rem #                  called this routine.
rem # 
rem #####################################################
label flip_screen
 setdispbuf curbuf 
 curbuf=1-curbuf
 setdrawbuf curbuf
return

rem #####################################################
rem # Procedure name : game_loop
rem # 
rem #        Details : The game housekeeping routine.
rem #
rem #####################################################
label game_loop
 score=0
 lives=3

 repeat
  for level=1 to maxlevels
   powerlife=0
   gamestate=1
   rem 1=playing
   rem 2=level clear
   rem 3=dead
   rem 4=quit

   gosub setup_level
   gosub reset_player
   gosub reset_ghosts

   for a=1 to 2
    gosub flip_screen
    clear window
    gosub draw_sidebar
    gosub draw_scores
    gosub display_lives
    gosub draw_whole_grid
   next a

   gosub ready

   repeat
    gosub flip_screen
    gosub undraw_player_area
    gosub undraw_ghosts

    gosub draw_player
    gosub draw_ghosts

    gosub move_player
    gosub move_ghosts

    gosub draw_scores

    gosub ghost_collision

    gosub pulse
    gosub power_decay
    gosub process_input

    if leveldots=0 then 
     gamestate=2
    fi

    if lives=0 then
     gamestate=3
    fi
   until (gamestate>1)

   if gamestate>2 then
    level=maxlevels
   fi

  next level
 until (gamestate>2)
return

rem #####################################################
rem # Procedure name : ready
rem # 
rem #        Details : Display the ready message and wait
rem #
rem #####################################################
label ready
 pulse=5
 gosub clear_status_line
 for ready_wait=255 to 1 step -2
  for a=1 to 2
   gosub display_lives
   gosub flip_screen
   gosub draw_ghosts
   gosub draw_player
   gosub clear_status_line
   setrgb 1,ready_wait,ready_wait,ready_wait
   text 225,500,"Get Ready","cc"
  next a
 next ready_wait
 for a=1 to 2
  gosub flip_screen
  gosub clear_status_line
 next a
return

rem #####################################################
rem # Procedure name : gameover
rem # 
rem #        Details : Display the game over message 
rem #                  and wait
rem #
rem #####################################################
label gameover
 pulse=5
 gosub clear_status_line
 for ready_wait=255 to 1 step -2
  for a=1 to 2
   gosub flip_screen
   gosub clear_status_line
   setrgb 1,ready_wait,ready_wait,ready_wait
   text 225,500,"Game Over","cc"
  next a
 next ready_wait
 for a=1 to 2
  gosub flip_screen
  gosub clear_status_line
  setrgb 1,255,255,255
  text 225,500,"Press X to Return to menu","cc"
 next a
 repeat
  joypad=peek("port1")
 until (and(joypad,16384)>0)
return

rem #####################################################
rem # Procedure name : clear_status_line
rem # 
rem #        Details : Clear the status line to black
rem #
rem #####################################################
label clear_status_line
  setrgb 1,0,0,0
  fill rectangle 0,485 to 640,512
return

rem #####################################################
rem # Procedure name : display_scroller
rem # 
rem #        Details : This routine displays the scroll
rem #                  text message.  As well as 
rem #                  displaying the message, it deals
rem #                  with everything to do with it.
rem #                  This includes advancing the text
rem #                  and looping back to the start.
rem # 
rem #####################################################
label display_scroller
 setrgb 1,0,0,0
 fill rectangle 0,480,640,512
 setrgb 1,255,255,255
 mx=mx-2
 if mx<=0 then 
  mx=mx+10
  mpos=mpos+1
  if mpos>len(m$) then
   mpos=0
  fi
 fi

 text mx,500,mid$(m$,mpos,64)
 setrgb 1,0,0,0
 fill rectangle 0,480 to 10,512
return

rem #####################################################
rem # Procedure name : draw_sidebar
rem # 
rem #        Details : This routine draws the main game
rem #                  sidebar
rem # 
rem #####################################################
label draw_sidebar
 setrgb 1,100,100,255
 fill rectangle 450,15 to 640,480

 rem hiscore
 setrgb 1,0,0,0
 text 465,70," High :"
 fill rectangle 540,58 to 625,73

 rem score
 setrgb 1,0,0,0
 text 465,100,"Score :"
 fill rectangle 540,88 to 625,103

 rem lives
 setrgb 1,0,0,0
 text 465,130,"Lives :"
 fill rectangle 540,118 to 625,133

return

rem #####################################################
rem # Procedure name : power_decay
rem # 
rem #        Details : This routine reduces the effect 
rem #                  of the powerpill
rem # 
rem #####################################################
label power_decay
 if powerlife>0 then
  powerlife=powerlife-1
 fi
return

rem #####################################################
rem # Procedure name : ghost_collision
rem # 
rem #        Details : This routine determines if the
rem #                  player hits a ghost
rem # 
rem #####################################################
label ghost_collision
 px=playerx*15+playerxo
 py=playery*15+playeryo

 for ghost=1 to 4
  if ghosts(ghost)=1 then
   gx=ghostx(ghost)*15+ghostxo
   gy=ghosty(ghost)*15+ghostyo

   if gx<px then
    gx=gx+15
   fi

   if gy<py then
    gy=gy+15
   fi

   if abs(px-gx)<8 and abs(py-gy)<8 then
    if powerlife=0 then
     players=2
    else
     ghosts(ghost)=2
     score=score+bonus
     bonus=bonus+bonus
    fi
   fi
  fi
 next ghost

 if players=2 then
  gosub kill_player
 fi
return

rem #####################################################
rem # Procedure name : kill_player
rem # 
rem #        Details : This routine kills the player
rem # 
rem #####################################################
label kill_player
 lives=lives-1

 for a=1 to 2
  gosub flip_screen
  gosub undraw_ghosts
  gosub undraw_player_area
 next a

 gosub reset_ghosts
 powerlife=0

 xpos=playerx*15+7+playerxo
 ypos=playery*15+7+playeryo

 setrgb 1,255,255,0
 for a=1 to 2
  gosub flip_screen
  fill circle xpos,ypos,10
 next a

 setrgb 1,0,0,0
 for angle=2 to 180 step 2
  for a=1 to 2
   gosub flip_screen
   fill triangle xpos,ypos to xpos+sines(angle)*11,ypos-cosines(angle)*11 to xpos+sines(angle-2)*11,ypos-cosines(angle-2)*11
   fill triangle xpos,ypos to xpos+sines(360-angle)*11,ypos-cosines(360-angle)*11 to xpos+sines(362-angle)*11,ypos-cosines(362-angle)*11
  next a
 next angle

 setrgb 1,255,255,0
 for a=1 to 2
  gosub flip_screen
  for angle=10 to 350 step 40
   line xpos+sines(angle)*6,ypos+cosines(angle)*6 to xpos+sines(angle)*10,ypos+cosines(angle)*10
  next angle
 next a

 wait 1

 for a=1 to 2
  gosub flip_screen
  gosub undraw_player_area
 next a

 gosub reset_player
 if lives>0 then
  gosub ready
 fi

 if lives=0 then
  gosub gameover
 fi
return

rem #####################################################
rem # Procedure name : reset_player
rem # 
rem #        Details : This routine resets the player
rem #                  position and status
rem # 
rem #####################################################
label reset_player
 playerx=playersx
 playery=playersy
 playerxo=0
 playeryo=0
 playerdir=4
 players=1
return

rem #####################################################
rem # Procedure name : reset_ghosts
rem # 
rem #        Details : This routine resets the ghost
rem #                  positions and status'
rem # 
rem #####################################################
label reset_ghosts
 for ghost=1 to 4
  ghostx(ghost)=ghosthx(ghost)
  ghostxo(ghost)=0
  ghostyo(ghost)=0
  ghosty(ghost)=ghosthy(ghost)
  ghostd(ghost)=0
  ghosts(ghost)=1
 next ghost
return

rem #####################################################
rem # Procedure name : draw_scores
rem # 
rem #        Details : This routine displays the hiscore
rem # 
rem #####################################################
label draw_scores
 if score>hiscore then
  hiscore=score
 fi
 setrgb 1,0,0,0
 fill rectangle 540,58 to 625,73
 fill rectangle 540,88 to 625,103
 setrgb 1,255,255,255
 text 545,70,str$(hiscore)
 text 545,100,str$(score)
return

rem #####################################################
rem # Procedure name : display_lives
rem # 
rem #        Details : This routine displays the lives
rem # 
rem #####################################################
label display_lives
 setrgb 1,0,0,0
 fill rectangle 540,118 to 625,133
 setrgb 1,255,255,255
 text 545,130,str$(lives)
return

rem #####################################################
rem # Procedure name : undraw_player_area
rem # 
rem #        Details : This routine redraws the player
rem #                  square and the surrounding area.
rem # 
rem #####################################################
label undraw_player_area
 sx=playerx-1
 sy=playery-1
 if playerxo>8 then 
  sx=sx+1
 fi
 if playeryo>8 then 
  sy=sy+1
 fi
 if sx<1 then sx=1 fi
 if sy<1 then sy=1 fi
 fx=sx+2
 fy=sy+2
 if fx>28 then fx=28 fi
 if fy>31 then fy=31 fi

 for x=sx to fx
  for y=sy to fy
   if map(x,y)<100 then
    gosub draw_grid_square
   fi
  next y
 next x
return

rem #####################################################
rem # Procedure name : clear_ghost
rem # 
rem #        Details : This routine clears the ghost
rem #                  square and the surrounding area
rem #                  from both buffers
rem # 
rem #####################################################
label clear_ghost
 for z=1 to 2
  gosub flip_screen
  gosub undraw_ghost_area
 next z
return

rem #####################################################
rem # Procedure name : undraw_ghosts
rem # 
rem #        Details : This routine redraws the ghosts
rem #                  and the surrounding area.
rem # 
rem #####################################################
label undraw_ghosts
 for ghost=1 to 4
  gosub undraw_ghost_area
 next ghost
return

rem #####################################################
rem # Procedure name : undraw_ghost_area
rem # 
rem #        Details : This routine redraws the ghost
rem #                  square and the surrounding area.
rem # 
rem #####################################################
label undraw_ghost_area
 sx=ghostx(ghost)-1
 sy=ghosty(ghost)-1
 if ghostxo(ghost)>8 then 
  sx=sx+1
 fi
 if ghostyo(ghost)>8 then 
  sy=sy+1
 fi
 if sx<1 then sx=1 fi
 if sy<1 then sy=1 fi
 fx=sx+2
 fy=sy+2
 if fx>28 then fx=28 fi
 if fy>31 then fy=31 fi

 for x=sx to fx
  for y=sy to fy
   if map(x,y)<100 then
    gosub draw_grid_square
   fi
  next y
 next x
return

rem #####################################################
rem # Procedure name : process_input
rem # 
rem #        Details : This routine deals with the player
rem #                  input via the controller
rem # 
rem #####################################################
label process_input
 buttons=peek("port1")

 if and(buttons,8)>0 then
  gosub quitgame
 fi

 if and(buttons,16)>0 and playery>1 then
  nt=map(playerx,playery-1)
  if playerxo=0 and nt<99 then
   playerdir=1
  fi
 fi

 if and(buttons,32)>0 and playerx<28 then
  nt=map(playerx+1,playery)
  if playeryo=0 and nt<99 then
   playerdir=2
  fi
 fi

 if and(buttons,64)>0 and playery<31 then
  nt=map(playerx,playery+1)
  if playerxo=0 and nt<99 then
   playerdir=3
  fi
 fi

 if and(buttons,128)>0 and playerx>1 then
  nt=map(playerx-1,playery)
  if playeryo=0 and nt<99 then
   playerdir=4
  fi
 fi
return

rem #####################################################
rem # Procedure name : draw_ghosts
rem # 
rem #        Details : This routine draws four ghosts
rem # 
rem #####################################################
label draw_ghosts
 for ghost=1 to 4

  xpos=int(ghostx(ghost)*15+ghostxo(ghost))
  ypos=int(ghosty(ghost)*15+ghostyo(ghost))

  if ghosts(ghost)=1 then
   if powerlife=0 then
    t=ghostt(ghost)
    if t=1 then
     setrgb 1,255,0,0
    fi

    if t=2 then
     setrgb 1,255,150,255
    fi

    if t=3 then
     setrgb 1,100,150,250
    fi

    if t=4 then
     setrgb 1,250,150,0
    fi
   else
    if powerlife>100 then
     setrgb 1,0,0,255
    else
     setrgb 1,pulse*30,pulse*30,255
    fi
   fi
   fill rectangle xpos-2,ypos-2 to xpos+18,ypos+18
  fi

  rem draw the whites of the eyes
  setrgb 1,255,255,255
  fill rectangle xpos,ypos+2 to xpos+6,ypos+8
  fill rectangle xpos+9,ypos+2 to xpos+15,ypos+8

  rem draw the pupils properly, based on direction
  setrgb 1,0,0,0
  d=ghostd(ghost)
  if d=0 then
   fill rectangle xpos+2,ypos+4 to xpos+4,ypos+6
   fill rectangle xpos+11,ypos+4 to xpos+13,ypos+6
  fi

  if d=1 then
   fill rectangle xpos+2,ypos+2 to xpos+4,ypos+4
   fill rectangle xpos+11,ypos+2 to xpos+13,ypos+4
  fi

  if d=2 then
   fill rectangle xpos+5,ypos+4 to xpos+7,ypos+6
   fill rectangle xpos+14,ypos+4 to xpos+16,ypos+6
  fi

  if d=3 then
   fill rectangle xpos+2,ypos+6 to xpos+4,ypos+8
   fill rectangle xpos+11,ypos+6 to xpos+13,ypos+8
  fi

  if d=4 then
   fill rectangle xpos,ypos+4 to xpos+2,ypos+6
   fill rectangle xpos+9,ypos+4 to xpos+11,ypos+6
  fi

  if ghosts(ghost)=1 then
   rem draw the skirt
   xpos=xpos+(pulse/2)
   for a=0 to 1
    fill rectangle xpos+a*7,ypos+15 to xpos+a*7+4,ypos+18
   next a
  fi

 next ghost
return

rem #####################################################
rem # Procedure name : draw_player
rem # 
rem #        Details : This routine draws the player
rem # 
rem #####################################################
label draw_player
 xpos=int(playerx*15+7+playerxo)
 ypos=int(playery*15+7+playeryo)
 mouth=pulse
 if mouth<0 then
  mouth=0
 fi

 setrgb 1,255,255,0
 fill circle xpos,ypos,10

 setrgb 1,0,0,0
 if playerdir=1 then
  fill triangle xpos,ypos to xpos-mouth,ypos-12 to xpos+mouth,ypos-12
 fi

 if playerdir=2 then
  fill triangle xpos,ypos to xpos+12,ypos+mouth to xpos+12,ypos-mouth
 fi

 if playerdir=3 then
  fill triangle xpos,ypos to xpos-mouth,ypos+12 to xpos+mouth,ypos+12
 fi

 if playerdir=4 then
  fill triangle xpos,ypos to xpos-12,ypos+mouth to xpos-12,ypos-mouth
 fi
return

rem #####################################################
rem # Procedure name : check_square
rem # 
rem #        Details : This routine checks the contents
rem #                  of the square the player has just
rem #                  arrived in to see what should 
rem #                  happen.
rem # 
rem #####################################################
label check_square
 t=map(playerx,playery)

 rem pill
 if t=2 then
  score=score+10
  map(playerx,playery)=0
  leveldots=leveldots-1
 fi

 rem power pill
 if t=3 then
  score=score+50
  map(playerx,playery)=0
  leveldots=leveldots-1
  if powerlife=0 then
   bonus=200
  fi
  powerlife=powerlife+400
 fi
return

rem #####################################################
rem # Procedure name : check_ghost_square
rem # 
rem #        Details : This routine checks the contents
rem #                  of the square the ghost has just
rem #                  arrived in to see what should 
rem #                  happen.
rem # 
rem #####################################################
label check_ghost_square
 if gx=ghosthx(ghost) and gy=ghosthy(ghost) then
  ghosts(ghost)=1
 fi

 rem warp tunnel
 if gx=28 then
  gosub clear_ghost
  gx=1
  return
 fi

 rem warp tunnel
 if gx=1 then
  gosub clear_ghost
  gx=28
  return
 fi

 rem warp tunnel
 if gy=31 then
  gosub clear_ghost
  gy=1
  return
 fi

 rem warp tunnel
 if gy=1 then
  gosub clear_ghost
  gy=31
  return
 fi

 rem dummy values
 tx=gx:ty=gy

 rem live aggressive ghost aims for player
 if ghostt(ghost)=1 and ghosts(ghost)=1 then
  tx=playerx
  ty=playery
  goto target_end
 fi

 rem live interceptor ghost aims for junction player is
 rem aiming for.
 if ghostt(ghost)=2 and ghosts(ghost)=1 then
  tx=playerx
  ty=playery

  rem player is heading up
  if playerdir=1 then
   done=0
   repeat
    if ty>1 then
     if map(tx,ty-1)<99 and overlay(tx,ty)<6 then
      ty=ty-1
     else
      done=1
     fi
    else
     done=1
    fi
   until (done=1)
   goto interceptor_done
  fi

  rem player is heading right
  if playerdir=2 then
   done=0
   repeat
    if tx<28 then
     if map(tx+1,ty)<99 and overlay(tx,ty)<6 then
      tx=tx+1
     else
      done=1
     fi
    else
     done=1
    fi
   until (done=1)
   goto interceptor_done
  fi

  rem player is heading down
  if playerdir=3 then
   done=0
   repeat
    if ty<31 then
     if map(tx,ty+1)<99 and overlay(tx,ty)<6 then
      ty=ty+1
     else
      done=1
     fi
    else
     done=1
    fi
   until (done=1)
   goto interceptor_done
  fi

  rem player is heading left
  if playerdir=4 then
   done=0
   repeat
    if tx>1 then
     if map(tx-1,ty)<99 and overlay(tx,ty)<6 then
      tx=tx-1
     else
      done=1
     fi
    else
     done=1
    fi
   until (done=1)
  fi
  label interceptor_done
 fi

 rem live interceptor ghost mk.2 stays around the middle
 if ghostt(ghost)=3 and ghosts(ghost)=1 then
  if gx>17 then tx=11 fi
  if gx<11 then tx=17 fi
  if gy>18 then ty=12 fi
  if gy<12 then ty=18 fi
 fi

 rem roamer ghost has no plans

 rem dead ghost aims for home
 if ghosts(ghost)=2 then
  tx=ghosthx(ghost)
  ty=ghosthy(ghost)
 fi

label target_end

 t=overlay(gx,gy)
 rem 0: wall
 rem 1: tunnel, no turning, carry on
 rem 2: dead end, face north
 rem 3: dead end, face east
 rem 4: dead end, face south
 rem 5: dead end, face west
 rem The rest are bitwise direction flags
 rem  128: north
 rem   64: east
 rem   32: south
 rem   16: west

 rem forced direction due to dead end
 if t>1 and t<6 then
  gd=t-1
 fi

 rem pick a direction that is free
 if t>5 then
  dn=0
  de=0
  ds=0
  dw=0

  if gd<>3 then
   if and(t,128)>1 then
    dn=1
   fi
  fi

  if gd<4 then
   if and(t,64)>1 then
    de=1
   fi
  fi

  if gd>1 then
   if and(t,32)>1 then
    ds=1
   fi
  fi

  if gd<>2 then
   if and(t,16)>1 then
    dw=1
   fi
  fi

  rem set the chosen direction to nothing.  If the AI
  rem fails to choose a direction, a random one will
  rem be picked.
  gd=0

  rem alive and vulnerable
  if ghosts(ghost)=1 and powerlife>0 then
   if de=1 and tx<gx then
    gd=2
   fi
   if dw=1 and tx>gx then
    gd=4
   fi
   if dn=1 and ty>gy then
    gd=1
   fi
   if ds=1 and ty<gy then
    gd=3
   fi
   goto ai_end
  fi

  rem non roamer or dead
  if ghostt(ghost)<4 or ghosts(ghost)=2 then
   if de=1 and tx>gx then
    gd=2
   fi
   if dw=1 and tx<gx then
    gd=4
   fi
   if dn=1 and ty<gy then
    gd=1
   fi
   if ds=1 and ty>gy then
    gd=3
   fi
   goto ai_end
  fi

label ai_end
  rem roamer or lost
  if ghostt(ghost)=4 or gd=0 then
   repeat
    choice=int(ran(4))+1
    if choice=1 and dn=1 then
     gd=1
    fi
    if choice=2 and de=1 then
     gd=2
    fi
    if choice=3 and ds=1 then
     gd=3
    fi
    if choice=4 and dw=1 then
     gd=4
    fi
   until (gd>0)
  fi
 fi
return

rem #####################################################
rem # Procedure name : move_player
rem # 
rem #        Details : This routine moves the player
rem #                  and also deals with the collision
rem #                  checking with the maze.
rem # 
rem #####################################################
label move_player
 if playerdir=1 then
  if playeryo>0 then
   playeryo=playeryo-1
   if playeryo=0 then
    gosub check_square
   fi
   return
  else
   if playery=1 then
    for a=1 to 2
     gosub flip_screen
     gosub undraw_player_area
    next a
    playery=31
    playeryo=0
   fi
   nt=map(playerx,playery-1)
   if nt<99 then
    playeryo=14
    playery=playery-1
   fi
  fi
 fi

 if playerdir=2 then
  if playerxo>0 and playerxo<15 then
   playerxo=playerxo+1
   if playerxo=15 then
    playerxo=0
    playerx=playerx+1
    gosub check_square
   fi
   return
  else
   if playerxo=15 then
    playerxo=0
    playerx=playerx+1
    gosub check_square
   fi
    if playerx=28 then
     for a=1 to 2
      gosub flip_screen
      gosub undraw_player_area
     next a
     playerx=1
     playerxo=0
    fi
   nt=map(playerx+1,playery)
   if nt<99 then
    playerxo=1
   fi
  fi
 fi

 if playerdir=3 then
  if playeryo>0 and playeryo<15 then
   playeryo=playeryo+1
   if playeryo=15 then
    playeryo=0
    playery=playery+1
    gosub check_square
   fi
   return
  else
   if playery=31 then
    for a=1 to 2
     gosub flip_screen
     gosub undraw_player_area
    next a
    playery=1
    playeryo=0
   fi
   if playeryo=15 then
    playeryo=0
    playery=playery+1
    gosub check_square
   fi
   nt=map(playerx,playery+1)
   if nt<99 then
    playeryo=1
   fi
  fi
 fi

 if playerdir=4 then
  if playerxo>0 then
   playerxo=playerxo-1
   if playerxo=0 then
    gosub check_square
   fi
   return
  else
    if playerx=1 then
     for a=1 to 2
      gosub flip_screen
      gosub undraw_player_area
     next a
     playerx=28
     playerxo=0
    fi
   nt=map(playerx-1,playery)
   if nt<99 then
    playerxo=14
    playerx=playerx-1
   fi
  fi
 fi
return

rem #####################################################
rem # Procedure name : move_ghosts
rem # 
rem #        Details : This routine moves the ghosts
rem # 
rem #####################################################
label move_ghosts

 for ghost=1 to 4
  gd=ghostd(ghost)
  gx=ghostx(ghost)
  gy=ghosty(ghost)
  gxo=ghostxo(ghost)
  gyo=ghostyo(ghost)

  if ghosts(ghost)=1 and curbuf=0 and powerlife>0 then
   goto ghost_move_end
  fi

  if gd=0 then
   gosub check_ghost_square
   goto ghost_move_end
  fi

  if gd=1 then
   if gyo>0 then
    gyo=gyo-1
    if gyo=0 then
     gosub check_ghost_square
    fi
    goto ghost_move_end
   else
    if gy=1 then
     for a=1 to 2
      gosub flip_screen
      gosub undraw_ghost_area
     next a
     gy=31
    fi
    if map(gx,gy-1)<>1 then
     gyo=14
     gy=gy-1
    fi
   fi
  fi

  if gd=2 then
   if gxo>0 and gxo<15 then
    gxo=gxo+1
    if gxo=15 then
     gxo=0
     gx=gx+1
     gosub check_ghost_square
    fi
    goto ghost_move_end
   else
    if gxo=15 then
     gxo=0
     gx=gx+1
     gosub check_ghost_square
    fi
     if gx=28 then
      for a=1 to 2
       gosub flip_screen
       gosub undraw_ghost_area
      next a
      gx=1
     fi
    if map(gx+1,gy)<>1 then
     gxo=1
    fi
   fi
  fi

  if gd=3 then
   if gyo>0 and gyo<15 then
    gyo=gyo+1
    if gyo=15 then
     gyo=0
     gy=gy+1
     gosub check_ghost_square
    fi
    goto ghost_move_end
   else
    if gy=31 then
     for a=1 to 2
      gosub flip_screen
      gosub undraw_ghost_area
     next a
     gy=1
    fi
    if gyo=15 then
     gyo=0
     gy=gy+1
     gosub check_ghost_square
    fi
    if map(gx,gy+1)<>1 then
     gyo=1
    fi
   fi
  fi

  if gd=4 then
   if gxo>0 then
    gxo=gxo-1
    if gxo=0 then
     gosub check_ghost_square
    fi
    goto ghost_move_end
   else
     if gx=1 then
      for a=1 to 2
       gosub flip_screen
       gosub undraw_ghost_area
      next a
      gx=28
     fi
    if map(gx-1,gy)<>1 then
     gxo=14
     gx=gx-1
    fi
   fi
  fi

label ghost_move_end
  ghostd(ghost)=gd
  ghostx(ghost)=gx
  ghosty(ghost)=gy
  ghostxo(ghost)=gxo
  ghostyo(ghost)=gyo
 next ghost
return

rem #####################################################
rem # Procedure name : pulse
rem # 
rem #        Details : This routine provides a bouncing
rem #                  variable that bounces from 0 to 8
rem #                  and back again. It is used for 
rem #                  things like the player's mouth.
rem # 
rem #####################################################
label pulse
 pulse=pulse+pulsedir
 if pulse<1 or pulse>7 then
  pulsedir=-pulsedir
 fi
return

rem #####################################################
rem # Procedure name : draw_grid_square
rem # 
rem #        Details : This routine draws a single square
rem #                  of the maze.
rem # 
rem #####################################################
label draw_grid_square
 t=map(x,y)
 xb=x*15
 yb=y*15

 if t=0 then
  setrgb 1,0,0,0
  fill rectangle xb-2,yb-2 to xb+18,yb+18
 fi

 if t>4 and t<9 then
  setrgb 1,0,0,0
  fill rectangle xb-2,yb-2 to xb+18,yb+18
 fi

 if t=2 then
  setrgb 1,0,0,0
  fill rectangle xb-2,yb-2 to xb+18,yb+18
  setrgb 1,255,255,0
  fill rectangle xb+6,yb+6 to xb+9,yb+9
 fi

 if t=3 then
  setrgb 1,0,0,0
  fill rectangle xb-2,yb-2 to xb+18,yb+18
  xpos=xb+7
  ypos=yb+7
  setrgb 1,255,0,0
  fill circle xpos,ypos,6
  setrgb 1,255,255,255
  fill rectangle xpos+1,ypos-2 to xpos+3,ypos+1
 fi

 if t=4 then
  setrgb 1,0,0,0
  fill rectangle xb-2,yb-2 to xb+18,yb+18
 fi

 if t=9 then
  setrgb 1,0,200,150
  fill rectangle xb,yb to xb+15,yb+15
 fi

 if t=99 then
  setrgb 1,0,0,0
  fill rectangle xb-6,yb-6 to xb+20,yb+20
  setrgb 1,0,200,150
  fill rectangle xb-6,yb+6 to xb+20,yb+9
 fi

 if t=100 then
  setrgb 1,0,0,255
  fill rectangle xb+6,yb+6 to xb+9,yb+9
 fi

 if t=101 then
  setrgb 1,0,0,255
  fill rectangle xb+6,yb to xb+9,yb+9
 fi

 if t=102 then
  setrgb 1,0,0,255
  fill rectangle xb+6,yb+6 to xb+15,yb+9
 fi

 if t=103 then
  setrgb 1,0,0,255
  fill rectangle xb+6,yb to xb+9,yb+9
  fill rectangle xb+6,yb+6 to xb+15,yb+9
 fi

 if t=104 then
  setrgb 1,0,0,255
  fill rectangle xb+6,yb+6 to xb+9,yb+15
 fi

 if t=105 then
  setrgb 1,0,0,255
  fill rectangle xb+6,yb to xb+9,yb+15
 fi

 if t=106 then
  setrgb 1,0,0,255
  fill rectangle xb+6,yb+6 to xb+9,yb+15
  fill rectangle xb+6,yb+6 to xb+15,yb+9
 fi

 if t=107 then
  setrgb 1,0,0,255
  fill rectangle xb+6,yb to xb+9,yb+15
  fill rectangle xb+6,yb+6 to xb+15,yb+9
 fi

 if t=108 then
  setrgb 1,0,0,255
  fill rectangle xb,yb+6 to xb+9,yb+9
 fi

 if t=109 then
  setrgb 1,0,0,255
  fill rectangle xb,yb+6 to xb+9,yb+9
  fill rectangle xb+6,yb to xb+9,yb+9
 fi

 if t=110 then
  setrgb 1,0,0,255
  fill rectangle xb,yb+6 to xb+15,yb+9
 fi

 if t=111 then
  setrgb 1,0,0,255
  fill rectangle xb,yb+6 to xb+15,yb+9
  fill rectangle xb+6,yb to xb+9,yb+9
 fi

 if t=112 then
  setrgb 1,0,0,255
  fill rectangle xb,yb+6 to xb+9,yb+9
  fill rectangle xb+6,yb+6 to xb+9,yb+15
 fi

 if t=113 then
  setrgb 1,0,0,255
  fill rectangle xb,yb+6 to xb+9,yb+9
  fill rectangle xb+6,yb to xb+9,yb+15
 fi

 if t=114 then
  setrgb 1,0,0,255
  fill rectangle xb,yb+6 to xb+15,yb+9
  fill rectangle xb+6,yb+6 to xb+9,yb+15
 fi

 if t=115 then
  setrgb 1,0,0,255
  fill rectangle xb,yb+6 to xb+15,yb+9
  fill rectangle xb+6,yb to xb+9,yb+15
 fi

return

rem #####################################################
rem # Procedure name : draw_whole_grid
rem # 
rem #        Details : This routine draws the whole maze
rem # 
rem #####################################################
label draw_whole_grid
 leveldots=0
 for x=1 to 28
  for y=1 to 31
   t=map(x,y)
   if t=2 or t=3 then
    leveldots=leveldots+1
   fi
   gosub draw_grid_square
  next y
 next x
return

rem #####################################################
rem # Procedure name : quitgame
rem # 
rem #        Details : This routine is essentially
rem #                  a pause with quit option
rem # 
rem #####################################################
label quitgame
 highlight=0
 repeat
  for a=1 to 2
   gosub flip_screen
   gosub clear_status_line
   setrgb 1,255,255,255
   text 150,500,"Quit Game?"
   if highlight=0 then
    setrgb 1,255,255,255
   else
    setrgb 1,100,100,100
   fi
   text 280,500,"No"

   if highlight=1 then
    setrgb 1,255,255,255
   else
    setrgb 1,100,100,100
   fi
   text 340,500,"Yes"
  next a

  joypad=peek("port1")
  if and(joypad,32)>0 then highlight=1 fi

  if and(joypad,128)>0 then highlight=0 fi

  if and(joypad,16384)>0 then
   for a=1 to 2
    gosub flip_screen
    gosub clear_status_line
   next a
   if highlight=1 then
    gamestate=4
   fi
  fi
 until (and(joypad,16384)>0)
return

rem #####################################################
rem # Procedure name : fine_tune_map
rem # 
rem #        Details : This routine fine tunes the map
rem #                  by determining which special
rem #                  blocks should be drawn for each
rem #                  square.
rem # 
rem #####################################################
label fine_tune_map
 for y=1 to 31
  for x=1 to 28
   if map(x,y)>99 then

    dirval=100
    if x>1 then
     if map(x-1,y)>99 then
      dirval=dirval+8
     fi
    fi

    if y>1 then
     if map(x,y-1)>99 then
      dirval=dirval+1
     fi
    fi

    if x<28 then
     if map(x+1,y)>99 then
      dirval=dirval+2
     fi
    fi

    if y<31 then
     if map(x,y+1)>99 then
      dirval=dirval+4
     fi
    fi

    map(x,y)=dirval
   fi
  next x
 next y
return

rem #####################################################
rem # Procedure name : setup_level
rem # 
rem #        Details : This routine sets up the current
rem #                  level by copying the map from the
rem #                  master copy into the map array.
rem #                  It also prepares the ghost overlay
rem # 
rem #####################################################
label setup_level
 for x=1 to 28
  for y=1 to 31
   rem map data
   map(x,y)=levels(level,x,y)

   rem prepare for the fine-tuning
   if map(x,y)=1 then
    map(x,y)=100
   fi

   if map(x,y)=9 then
    map(x,y)=99
   fi

   rem we found a ghost home square
   if map(x,y)>4 and map(x,y)<9 then
    ghosthx(map(x,y)-4)=x
    ghosthy(map(x,y)-4)=y
   fi

   rem we found the player start square
   if map(x,y)=4 then
    playersx=x
    playersy=y
   fi

   if map(x,y)<>1 then
    overlay(x,y)=1
    rem overlay data
    numdirs=0
    dirval=0
    if x>1 then
     if levels(level,x-1,y)<>1 then
      numdirs=numdirs+1
      dirval=dirval+16
     fi
    fi

    if y>1 then
     if levels(level,x,y-1)<>1 then
      numdirs=numdirs+1
      dirval=dirval+128
     fi
    fi

    if x<28 then
     if levels(level,x+1,y)<>1 then
      numdirs=numdirs+1
      dirval=dirval+64
     fi
    fi

    if y<31 then
     if levels(level,x,y+1)<>1 then
      numdirs=numdirs+1
      dirval=dirval+32
     fi
    fi

    if numdirs=1 then
     if dirval=128 then
      overlay(x,y)=2
     fi
     if dirval=64 then
      overlay(x,y)=3
     fi
     if dirval=32 then
      overlay(x,y)=4
     fi
     if dirval=16 then
      overlay(x,y)=5
     fi
    fi

    if numdirs>1 then
     if dirval=160 or dirval=80 then
      overlay(x,y)=1
     else
      overlay(x,y)=dirval
     fi
    fi
   fi

   rem tunnels are tunnels, keep going
   if x=1 or x=28 or y=1 or y=31 then
    overlay(x,y)=1
   fi

   rem ghost door is a tunnel, keep going
   if map(x,y)=99 then
    overlay(x,y)=1
   fi
  next y
 next x

 for a=1 to 4
  ghostx(a)=ghosthx(a)
  ghosty(a)=ghosthy(a)
  ghostd(a)=0
  ghostt(a)=a
  ghosts(a)=1
 next a

 gosub fine_tune_map
return

rem #####################################################
rem # Procedure name : setup_instructions
rem # 
rem #        Details : This routine sets up the 
rem #                  instructions.
rem # 
rem #####################################################
label setup_instructions
 instructlines=22
 dim in$(instructlines)
 for a=1 to instructlines
  in$(a)=""
 next a

 in$(1)="Paccy is a hungry little circle. He likes to"
 in$(2)="eat yellow dots, lots of them.  If you help"
 in$(3)="him to eat dots, he will reward you."
 in$(5)="So, you guide Paccy around the maze, and he"
 in$(6)="gives you points.  Sounds easy?  Well, it"
 in$(7)="would be if it wasn't for the ghosts.  These"
 in$(8)="ghosts are trying to stop Paccy from eating"
 in$(9)="the dots.  If they touch Paccy, they make him"
 in$(10)="regurgitate the dots, leaving him hungry"
 in$(11)="again."
 in$(13)="Paccy isn't without his defences though.  If"
 in$(14)="you can help him get to a red power pill,"
 in$(15)="the ghosts turn blue for a while, and Paccy"
 in$(16)="can steal their cloaks.  The ghosts will then"
 in$(17)="have to run back to their hideouts to get a"
 in$(18)="new cloak."
 in$(20)="Paccy has decided to give you 10 points for a"
 in$(21)="yellow dot, 50 points for a power pill, and "
 in$(22)="a special bonus each time you steal a cloak."
return

rem #####################################################
rem # Procedure name : setup_scroller
rem # 
rem #        Details : This routine sets up the scroll
rem #                  text message.  That's all it does.
rem # 
rem #####################################################
label setup_scroller
 rem title screen scroller
 ti$="                                                 "
 ti$=ti$+"                    "
 ti$=ti$+"Welcome to Paccy, a game that bears a striking "
 ti$=ti$+"similarity to a game that was very popular in "
 ti$=ti$+"the 1980's.  "
 ti$=ti$+"The controls are easy enough, you simply use "
 ti$=ti$+"the joypad to guide the main character (paccy, "
 ti$=ti$+"the hungry yellow circle) around the maze.  "
 ti$=ti$+"The object of the game is to eat all of the "
 ti$=ti$+"yellow dots, whilst avoiding the coloured "
 ti$=ti$+"ghosts.  If a ghost should come into contact "
 ti$=ti$+"with you, you lose a life.  Lose all of your "
 ti$=ti$+"lives and it's game over.  "
 ti$=ti$+"You can get your own back on the ghosts though,"
 ti$=ti$+" with the aid of the red power pills.  Eating "
 ti$=ti$+"one of these makes all of the ghosts turn blue."
 ti$=ti$+"  When the ghosts are blue, you can eat THEM!  "
 ti$=ti$+"On most of the mazes, there are tunnels at the "
 ti$=ti$+"edge of the maze.  These tunnels allow you and "
 ti$=ti$+"the ghosts to quickly travel to the opposite "
 ti$=ti$+"side of the maze.  "
 ti$=ti$+"I hope you have as much fun (and frustration) "
 ti$=ti$+"as I did when writing it.   "
 ti$=ti$+"Now for a few hello's...."
 ti$=ti$+"Hiya doctor, keep up the good work and "
 ti$=ti$+"determination.  Mr. Shockwave, keep those "
 ti$=ti$+"demos and games coming.  Rafryer. Jacob busby."
 ti$=ti$+"  Master Tonberry.  Ps2yabasic, "
 ti$=ti$+"thank you again and again for giving us the "
 ti$=ti$+"site.  And to everyone else I have momentarily "
 ti$=ti$+"forgotten."

 rem menu screen scroller
 me$="                                                 "
 me$=me$+"                    "
 me$=me$+"Use the up and down buttons to move the "
 me$=me$+"highlight bar, and press X to select the "
 me$=me$+"option.  "
 me$=me$+"The 'Start Game' option starts the game using "
 me$=me$+"the current options.  "
 me$=me$+"The 'Instructions' option explains how the "
 me$=me$+"game is played and scored.  "
 me$=me$+"Finally, the 'Return to title' option returns "
 me$=me$+"you to the main title screen."
return

rem #####################################################
rem # Procedure name : initialise
rem # 
rem #        Details : This routine sets up all of the
rem #                  global variables and arrays.  I've
rem #                  placed it at the end of the code
rem #                  because it's out of the way and 
rem #                  can easily be reached by pressing
rem #                  the CTRL and END keys together.
rem # 
rem #####################################################
label initialise
 sw=640          : rem screen width
 sh=512          : rem screen height
 open window sw,sh

 curbuf=0        : rem current screen buffer
 maxlevels=5     : rem how many maps
 level=1         : rem level
 lives=3         : rem lives
 hiscore=0       : rem hiscore
 score=0         : rem score
 leveldots=0     : rem how many dots left in the level
 powerlife=0     : rem time left of the power up
 bonus=0         : rem bonus points for eating a ghost

 pulse=0
 pulsedir=1

 playersx=0     : rem start x position
 playersy=0     : rem start y position
 playerx=0       : rem x position
 playery=0       : rem y position
 playerdir=4     : rem direction
 playerxo=0      : rem x offset
 playeryo=0      : rem y offset
 players=1       : rem state
                   rem   1: alive
                   rem   2: dying

 dim ghostx(4)   : rem x position
 dim ghosty(4)   : rem y position
 dim ghostxo(4)  : rem x offset
 dim ghostyo(4)  : rem y offset
 dim ghosthx(4)  : rem ghost home x
 dim ghosthy(4)  : rem ghost home y
 dim ghostt(4)   : rem type
                   rem   1: aggressor
                   rem   2: interceptor
                   rem   3: interceptor 2
                   rem   4: roamer
 dim ghostd(4)   : rem direction
 dim ghosts(4)   : rem state
                   rem   1: alive
                   rem   2: dead

 dim cosines(360)
 dim sines(360)

 for angle=0 to 360
  cosines(angle)=cos(angle*(pi/180))
  sines(angle)=sin(angle*(pi/180))
 next angle

 setrgb 0,0,0,0
 clear window
 setrgb 1,255,255,255
 text 320,100,"Processing Level Data","cc"

 text 100,190,"Total Levels :"+str$(maxlevels)
 text 100,290,"Current Level :"

 setrgb 1,0,0,255
 rectangle 100,200 to 500,220
 dim levels(maxlevels,28,31)
 restore map_data
 bar1pos=100
 bar1inc=400/(31*28*maxlevels)
 bar2inc=400/(31*28)
 for a=1 to maxlevels
  setrgb 1,0,0,0
  fill rectangle 100,300 to 500,320
  fill rectangle 250,270 to 300,296
  setrgb 1,255,255,255
  text 250,290,str$(a)

  setrgb 1,0,0,255
  rectangle 100,300 to 500,320
  bar2pos=100
  for y=1 to 31
   read l$
   for x=1 to 28
    s$=mid$(l$,x,1)

    rem wall
    if s$="%" then
     levels(a,x,y)=1
     goto mapreadnextx
    fi

    rem dot
    if s$="." then
     levels(a,x,y)=2
     goto mapreadnextx
    fi

    rem blank
    if s$=" " then
     levels(a,x,y)=0
     goto mapreadnextx
    fi

    rem power pill
    if s$="o" then
     levels(a,x,y)=3
     goto mapreadnextx
    fi

    rem ghost door
    if s$="-" then
     levels(a,x,y)=9
     goto mapreadnextx
    fi

    rem player
    if s$="C" then
     levels(a,x,y)=4
     goto mapreadnextx
    fi

    rem ghost 1
    if s$="5" then
     levels(a,x,y)=5
     goto mapreadnextx
    fi

    rem ghost 2
    if s$="6" then
     levels(a,x,y)=6
     goto mapreadnextx
    fi

    rem ghost 3
    if s$="7" then
     levels(a,x,y)=7
     goto mapreadnextx
    fi

    rem ghost 4
    if s$="8" then
     levels(a,x,y)=8
    fi

label mapreadnextx
   bar1pos=bar1pos+bar1inc
   bar2pos=bar2pos+bar2inc
   line bar1pos,200 to bar1pos,220
   line bar2pos,300 to bar2pos,320
   next x
  next y
 next a

 rem a copy of the basic data for this attempt, meaning
 rem that the original data is not damaged.
 dim map(28,31)

 rem The overlay array.
 rem the following array is used to inform the ghosts
 rem of what type of square they have just landed on.
 rem the values are as follows:
 rem
 rem 0: wall
 rem 1: tunnel, no turning, carry on
 rem 2: dead end, face north
 rem 3: dead end, face east
 rem 4: dead end, face south
 rem 5: dead end, face west
 rem The rest are bitwise direction flags
 rem  128: north
 rem   64: east
 rem   32: south
 rem   16: west
 dim overlay(28,31)

 gosub setup_instructions
 gosub setup_scroller
return

rem map data
rem 0=black
rem 1=wall
rem 2=pill
rem 3=power pill
rem 4=player start
rem 5=ghost1 start
rem 6=ghost2 start
rem 7=ghost3 start
rem 8=ghost4 start
rem 9=ghost door

label map_data
rem map one
data "%%%%%%%%%%%%%%%%%%%%%%%%%%%%"
data "%............%%............%"
data "%.%%%%.%%%%%.%%.%%%%%.%%%%.%"
data "%o%  %.%   %.%%.%   %.%  %o%"
data "%.%%%%.%%%%%.%%.%%%%%.%%%%.%"
data "%..........................%"
data "%.%%%%.%%.%%%%%%%%.%%.%%%%.%"
data "%.%%%%.%%.%%%%%%%%.%%.%%%%.%"
data "%......%%....%%....%%......%"
data "%%%%%%.%%%%% %% %%%%%.%%%%%%"
data "     %.%%%%% %% %%%%%.%     "
data "     %.%%          %%.%     "
data "     %.%% %%%--%%% %%.%     "
data "%%%%%%.%% %%%--%%% %%.%%%%%%"
data "      .   %%5678%%   .      "
data "%%%%%%.%% %%%%%%%% %%.%%%%%%"
data "     %.%% %%%%%%%% %%.%     "
data "     %.%%          %%.%     "
data "     %.%% %%%%%%%% %%.%     "
data "%%%%%%.%% %%%%%%%% %%.%%%%%%"
data "%............%%............%"
data "%.%%%%.%%%%%.%%.%%%%%.%%%%.%"
data "%.%%%%.%%%%%.%%.%%%%%.%%%%.%"
data "%o..%%....... C.......%%..o%"
data "%%%.%%.%%.%%%%%%%%.%%.%%.%%%"
data "%%%.%%.%%.%%%%%%%%.%%.%%.%%%"
data "%......%%....%%....%%......%"
data "%.%%%%%%%%%%.%%.%%%%%%%%%%.%"
data "%.%%%%%%%%%%.%%.%%%%%%%%%%.%"
data "%..........................%"
data "%%%%%%%%%%%%%%%%%%%%%%%%%%%%"

rem map two
data "%%%%%% %%%%%%%%%%%%%% %%%%%%"
data "%....% %.....%%.....% %....%"
data "%.%%%% %%%%%.%%.%%%%% %%%%.%"
data "%o%  % %   %.%%.%   % %  %o%"
data "%.%%%% %%%%%.%%.%%%%% %%%%.%"
data "%..........................%"
data "%%%%%%.%%.%%%%%%%%.%%.%%%%%%"
data "%%%%%%.%%.%%%%%%%%.%%.%%%%%%"
data "      .%%....%%....%%.      "
data "%%%%%%.%%%%% %% %%%%%.%%%%%%"
data "%.%  %.%%%%% %% %%%%%.%  %.%"
data "%.%  %.%%          %%.%  %.%"
data "%.%  %.%% %%%--%%% %%.%  %.%"
data "%.%%%%.%% %%%--%%% %%.%%%%.%"
data "%......   %%5678%%   ......%"
data "%.%%%%.%% %%%%%%%% %%.%%%%.%"
data "%.%  %.%% %%%%%%%% %%.%  %.%"
data "%.%  %.%%          %%.%  %.%"
data "%.%  %.%% %%%%%%%% %%.%  %.%"
data "%%%%%%.%% %%%%%%%% %%.%%%%%%"
data "      .......%%.......      "
data "%%%%%%.%%%%%.%%.%%%%%.%%%%%%"
data "%%%%%%.%%%%%.%%.%%%%%.%%%%%%"
data "%o..%%....... C.......%%..o%"
data "%%%.%%.%%.%%%%%%%%.%%.%%.%%%"
data "%%%.%%.%%.%%%%%%%%.%%.%%.%%%"
data "%............%%............%"
data "%.%%.% %.%%%.%%.%%%.% %.%%.%"
data "%.%%.% %.%%%.%%.%%%.% %.%%.%"
data "%....% %............% %....%"
data "%%%%%% %%%%%%%%%%%%%% %%%%%%"

rem map three
data "%%%%%%%%%%%%%%%%%%%%%%%%%%%%"
data "%..........................%"
data "%.%%%%.%%%%%.%%.%%%%%.%%%%.%"
data "%o%  %.% 5 %.%%.% 6 %.%  %o%"
data "%.%%%%.%%-%%.%%.%%-%%.%%%%.%"
data "%..........................%"
data "%%%.%%.%%.%%%%%%%%.%%.%%.%%%"
data "%%%.%%.%%.%%%%%%%%.%%.%%.%%%"
data "%......%%....%%....%%......%"
data "%.%%%%.%%%%%.%%.%%%%%.%%%%.%"
data "%.%  %.%%%%%.%%.%%%%%.%  %.%"
data "%.%  %.%%..........%%.%  %.%"
data "%.%  %.%%.%%%%%%%%.%%.%  %.%"
data "%.%%%%.%%.%%%%%%%%.%%.%%%%.%"
data "%o........................o%"
data "%.%%%%.%%.%%%%%%%%.%%.%%%%.%"
data "%.%  %.%%.%%%%%%%%.%%.%  %.%"
data "%.%  %.%%..........%%.%  %.%"
data "%.%  %.%%.%%%%%%%%.%%.%  %.%"
data "%.%%%%.%%.%%%%%%%%.%%.%%%%.%"
data "%............%%............%"
data "%.%%%%.%%%%%.%%.%%%%%.%%%%.%"
data "%.%%%%.%%%%%.%%.%%%%%.%%%%.%"
data "%o..%%....... C.......%%..o%"
data "%.%.%%.%%.%%%%%%%%.%%.%%.%.%"
data "%.%.%%.%%.%%%%%%%%.%%.%%.%.%"
data "%.%.%%.......%%.......%%.%.%"
data "%.....%%.%%%.%%.%%%.%%.....%"
data "%%-%%.%%.%%%.%%.%%%.%%.%%-%%"
data "% 7 %..................% 8 %"
data "%%%%%%%%%%%%%%%%%%%%%%%%%%%%"

rem map four
data "%%%%%%%%%%%%    %%%%%%%%%%%%"
data "%o.........%    %.........o%"
data "%.%%%%.%%%.%    %.%%%.%%%%.%"
data "%.%  %.% %.%    %.% %.%  %.%"
data "%.%  %.% %.%    %.% %.%  %.%"
data "%.%  %.% %.%    %.% %.%  %.%"
data "%.%  %.% %.%%%%%%.% %.%  %.%"
data "%.% %%.%%%........%%%.%% %.%"
data "%.%%%......%%%%%%......%%%.%"
data "%.....%%%%.%    %.%%%%.....%"
data "%.%%%.%  %.%    %.%  %.%%%.%"
data "%.% %.%%%%.%    %.%%%%.% %.%"
data "%.% %......%%%%%%......% %.%"
data "%.%%%.%%%%........%%%%.%%%.%"
data "%o....%  %.%%--%%.%  %....o%"
data "%.%%%.%  %.%5678%.%  %.%%%.%"
data "%.% %.%  %.%%%%%%.%  %.% %.%"
data "%.%%%.%%%%........%%%%.%%%.%"
data "%..........%%%%%%..........%"
data "%.%%%%.%%%.%    %.%%%.%%%%.%"
data "%.%  %.% %.%    %.% %.%  %.%"
data "%.%  %.%%%.%    %.%%%.%  %.%"
data "%.% %%.....%%%%%%.....%% %.%"
data "%.% %..%%%... C...%%%..% %.%"
data "%.%%%.%% %%.%%%%.%% %%.%%%.%"
data "%.....%   %.%  %.%   %.....%"
data "%.%%%.%  %%.%  %.%%  %.%%%.%"
data "%.% %.%  %..%  %..%  %.% %.%"
data "%.%%%.%%%%.%%  %%.%%%%.%%%.%"
data "%o.........%    %.........o%"
data "%%%%%%%%%%%%    %%%%%%%%%%%%"

rem map five
data "%%%%%%%%%%%%%%%%%%%%%%%%%%%%"
data "%o........................o%"
data "%.%%%%%%%%.%%%%%%.%%%%%%%%.%"
data "%.%      %.%    %.%      %.%"
data "%.%%%%%%%%.%%%%%%.%%%%%%%%.%"
data "%..........................%"
data "%%.%%%.%%%%%%%%%%%%%%.%%%.%%"
data " %.%....................%.% "
data " %.%.%%%%%.%%%%%%.%%%%%.%.% "
data " %.%.%................%.%.% "
data " %.%.%.%.%%%%%%%%%%.%.%.%.% "
data " %.%.%.%............%.%.%.% "
data " %.%.%.%.%%%%%%%%%%.%.%.%.% "
data " %.%.%.%.%........%.%.%.%.% "
data " %.%.%.%.%.%%--%%.%.%.%.%.% "
data " %o%...%...%5678%...%...%o% "
data " %.%.%.%.%.%%%%%%.%.%.%.%.% "
data " %.%.%.%.%........%.%.%.%.% "
data " %.%.%.%.%%%%%%%%%%.%.%.%.% "
data " %.%.%.%............%.%.%.% "
data " %.%.%.%.%%%%%%%%%%.%.%.%.% "
data " %.%.%................%.%.% "
data " %.%.%%%%%.%%%%%%.%%%%%.%.% "
data " %.%......... C.........%.% "
data "%%.%%%.%%%%%%%%%%%%%%.%%%.%%"
data "%..........................%"
data "%.%%%%%%%%.%%%%%%.%%%%%%%%.%"
data "%.%      %.%    %.%      %.%"
data "%.%%%%%%%%.%%%%%%.%%%%%%%%.%"
data "%o........................o%"
data "%%%%%%%%%%%%%%%%%%%%%%%%%%%%"

