global screenx=1024
global screeny=768
set display mode screenx,screeny,32
hide mouse
backdrop on
color backdrop 0
sync on
global xoff
xoff=int(screenx/2)
global yoff
yoff=int(screeny/2)
 
rem Set up sounds
for nums=1 to 4
  make_sound(nums)
next nums
set sound volume 1,80
set sound volume 2,80
set sound volume 3,80
set sound volume 4,90
 
rem Setup forcefield
global dim forcefield(2,11)
global dim angle#(2)
global dim shell(2)
global dim shell_top(2)
global rad=50
shell_top(0)=0
shell_top(1)=20
shell_top(2)=40
shell(0)=shell_top(0)
shell(1)=shell_top(1)
shell(2)=shell_top(2)
 
rem Setup ship
global ship_x#
global ship_y#
global ship
ship_a#=0.0
ship_step#=1.0
global ship_xp#=0.0
global ship_yp#=0.0
ship_max#=2.0
global dim sx#(50)
global dim sy#(50)
global dim sxp#(50)
global dim syp#(50)
global s_c=0
drag#=0.997
global shipfield=0
global shipfieldp=255
global shipfieldr=50
 
rem Set up target
t_a#=0.0
global target=0
global dim tx#(50)
global dim ty#(50)
global dim txp#(50)
global dim typ#(50)
global t_c=0
global target_shoot=0
global tsx#
global tsy#
global tsxp#
global tsyp#
 
rem Setup ammo
global shots=3
global dim ship_shotx#(3)
global dim ship_shoty#(3)
global dim ship_shotxp#(3)
global dim ship_shotyp#(3)
global dim ship_shot(3)
global fire=50
 
rem Set up chasers
global chasers=2
global dim cx#(chasers)
global dim cy#(chasers)
global dim cxp#(chasers)
global dim cyp#(chasers)
global dim c_a(chasers)
global dim c_d(chasers)
 
rem Set up scores
global ships=3
global level=1
 
rem Initialize
gosub reset_ship
gosub reset_target
 
instructions()
quit=0
while quit=0
  checkpoint=timer()
  draw_forcefield()
  draw_ship(ship_x#,ship_y#,ship_a#)
  draw_target(t_a#)
  draw_shots()
  display_score()
  if ship=0 and target=0 then draw_chasers()
  if ship=0 and target=0 then check_collision()
  if ship=0 and target=0 then check_shot(t_a#)
  sync
  if leftkey()
    ship_a#=ship_a#-ship_step#
    if ship_a#<0.0 then ship_a#=ship_a#+360.0
  endif
  if rightkey()
    ship_a#=ship_a#+ship_step#
    if ship_a#>360.0 then ship_a#=ship_a#-360.0
  endif
  if upkey()
    new_ship_xp#=ship_xp#+cos(ship_a#)/50.0
    new_ship_yp#=ship_yp#+sin(ship_a#)/50.0
    if abs(new_ship_xp#)<ship_max# and abs(new_ship_yp#)<ship_max#
      ship_xp#=new_ship_xp#
      ship_yp#=new_ship_yp#
    endif
  endif
  if controlkey()
    shipfield=1
  else
    shipfield=0
  endif
  if shipfield=1
    if shipfieldr=0
      dec shipfieldp
      if shipfieldp<0 then shipfieldp=0
    endif
    dec shipfieldr
    if shipfieldr<0 then shipfieldr=10
  endif
  if spacekey() and fire=0 and shipfield=0
    fire=50
    for x=1 to shots
      if ship_shot(x)=0
        ship_shotx#(x)=cos(ship_a#)*10.0+ship_x#
        ship_shoty#(x)=sin(ship_a#)*10.0+ship_y#
        ship_shotxp#(x)=cos(ship_a#)*4.0
        ship_shotyp#(x)=sin(ship_a#)*4.0
        ship_shot(x)=160
        x=shots
      endif
    next x
    play sound 1
  endif
  if fire>0 then dec fire
  ship_x#=ship_x#+ship_xp#
  if ship_x#<-xoff then ship_x#=ship_x#+screenx
  if ship_x#>xoff then ship_x#=ship_x#-screenx
  ship_xp#=ship_xp#*drag#
  ship_y#=ship_y#+ship_yp#
  if ship_y#<-yoff then ship_y#=ship_y#+screeny
  if ship_y#>yoff then ship_y#=ship_y#-screeny
  ship_yp#=ship_yp#*drag#
  t_a#=atan(ship_y#/ship_x#)
  if ship_x#<0.0 then t_a#=t_a#+180.0
  if ships=0
    game_over()
    quit=1
  endif
  set cursor 0,100
rem  while timer()-checkpoint<5
rem  endwhile
endwhile
 
end
reset_ship:
  ship_x#=300.0
  ship_y#=-200.0
  ship=0
  ship_a#=0.0
  ship_xp#=0.0
  ship_yp#=0.0
  for x=1 to shots
    ship_shot(x)=0
  next x
  shipfieldp=255
  gosub reset_chasers
return
reset_target:
  target=0
  for x=0 to 2
    for y=0 to 11
      forcefield(x,y)=2
    next y
    angle#(x)=0
  next x
  gosub reset_chasers
return
reset_chasers:
  for x=1 to chasers
    if x<level
      c_a(x)=1
      c_d(x)=x*50
    endif
    cx#(x)=0.0
    cy#(x)=0.0
  next x
return
function display_score()
  for x=1 to ships
    line screenx-(x*10),0,screenx-(x*10)-5,10
    line screenx-(x*10),0,screenx-(x*10)+5,10
    line screenx-(x*10)-5,10,screenx-(x*10),5
    line screenx-(x*10)+5,10,screenx-(x*10),5
  next x
  set cursor 0,0
  print "Level ";level
endfunction
function check_collision()
  set cursor 0,0
  for x=1 to shots
    if ship_shot(x)>0
      radius#=sqrt(ship_shotx#(x)^2+ship_shoty#(x)^2)
      if radius#<40.0+rad
        if radius#>30.0+rad
          fieldposition(2,x,1,ship_shotx#(x),ship_shoty#(x))
        else
          if radius#>20.0+rad
            fieldposition(1,x,1,ship_shotx#(x),ship_shoty#(x))
          else
            if radius#>rad
              fieldposition(0,x,1,ship_shotx#(x),ship_shoty#(x))
            else
              if radius#<20.0 and target=0
                play sound 3
                explode_target(x)
              endif
            endif
          endif
        endif
      endif
    endif
    for i=1 to chasers
      radius#=sqrt((ship_shotx#(x)-cx#(i))^2+(ship_shoty#(x)-cy#(i))^2)
      if radius#<9.0
        explode_chaser(x,i)
      endif
    next i
  next x
  if target_shoot=1 and ship=0
    radius#=sqrt((ship_x#-tsx#)^2+(ship_y#-tsy#)^2)
    if radius#<16.0
      explode_ship()
    endif
  endif
  radius#=sqrt(ship_x#^2+ship_y#^2)
  if radius#<40.0+rad
    if radius#>30.0+rad
      if fieldposition(2,x,2,ship_x#,ship_y#)=1
        explode_ship()
      endif
    else
      if radius#>20.0+rad
        if fieldposition(1,x,2,ship_x#,ship_y#)=1
          explode_ship()
        endif
      else
        if radius#>rad
          if fieldposition(0,x,2,ship_x#,ship_y#)=1
            explode_ship()
          endif
        endif
      endif
    endif
  endif
endfunction
function check_shot(a#)
  shotx#=cos(a#)*rad
  shoty#=sin(a#)*rad
  path=fieldposition(0,0,0,shotx#,shoty#)
  shotx#=cos(a#)*(20.0+rad)
  shoty#=sin(a#)*(20.0+rad)
  path=path+fieldposition(1,0,0,shotx#,shoty#)
  shotx#=cos(a#)*(40.0+rad)
  shoty#=sin(a#)*(40.0+rad)
  path=path+fieldposition(2,0,0,shotx#,shoty#)
  if path=0 and target_shoot=0 and ship=0
    target_shot(a#)
  endif
endfunction
function explode_chaser(x,i)
  ship_shot(x)=0
  c_a(i)=0
endfunction
function explode_ship()
  target_shoot=0
  explode=1
  if shipfield=1
    ship_xp#=-ship_xp#
    ship_yp#=-ship_yp#
    shipfieldp=shipfieldp-50
    explode=0
    if shipfieldp<0
      shipfieldp=0
      explode=1
    endif
    shipfield=0
  endif
  if explode=1
    ship=1
    s_c=255
    for i=1 to 50
      sx#(i)=ship_x#
      sy#(i)=ship_y#
      sxp#(i)=(rnd(60)-30)/100.0
      syp#(i)=(rnd(60)-30)/100.0
    next i
    ship_xp#=0.0
    ship_yp#=0.0
    play sound 3
  endif
endfunction
function explode_target(x)
  ship_shot(x)=0
  target=1
  t_c=255
  for i=1 to 50
    tx#(i)=0.0
    ty#(i)=0.0
    txp#(i)=(rnd(60)-30)/100.0
    typ#(i)=(rnd(60)-30)/100.0
  next i
endfunction
function fieldposition(a,x,c,shotx#,shoty#)
  returnvalue=0
  shot_angle=atan(shoty#/shotx#)
  if shotx#<0.0 then shot_angle=shot_angle+180
  shot_angle=shot_angle-int(angle#(a))
  while shot_angle<0
    shot_angle=shot_angle+360
  endwhile
  if shot_angle>360 then shot_angle=shot_angle-360
  fieldshot=int(shot_angle/30)
  if c=2
    if forcefield(a,fieldshot)>0
      dec forcefield(a,fieldshot)
      play sound 2
      returnvalue=1
    endif
  endif
  if c=1
    if forcefield(a,fieldshot)>0
      dec forcefield(a,fieldshot)
      ship_shot(x)=0
      returnvalue=1
      found=0
      for x=1 to shots
        if ship_shot(x)>0 then found=1
      next x
      if found=0 then fire=0
      play sound 2
    endif
  endif
  if c=0
    returnvalue=forcefield(a,fieldshot)
  endif
endfunction returnvalue
function target_shot(a#)
  play sound 4
  target_shoot=1
  tsx#=cos(a#)*20.0
  tsy#=sin(a#)*20.0
  tsxp#=tsx#/5.0
  tsyp#=tsy#/5.0
endfunction
function draw_shots()
  ink rgb(255,0,0),0
  for x=1 to shots
    if ship_shot(x)>0
      circle ship_shotx#(x)+xoff,ship_shoty#(x)+yoff,2
      ship_shotx#(x)=ship_shotx#(x)+ship_shotxp#(x)
      if ship_shotx#(x)<-xoff then ship_shotx#(x)=ship_shotx#(x)+screenx
      if ship_shotx#(x)>xoff then ship_shotx#(x)=ship_shotx#(x)-screenx
      ship_shoty#(x)=ship_shoty#(x)+ship_shotyp#(x)
      if ship_shoty#(x)<-yoff then ship_shoty#(x)=ship_shoty#(x)+screeny
      if ship_shoty#(x)>yoff then ship_shoty#(x)=ship_shoty#(x)-screeny
      dec ship_shot(x)
    endif
  next x
  if target_shoot=1
    for a=5 to 355 step 20
      ray=rnd(15)+4
      x=cos(a)*ray
      y=sin(a)*ray
      line tsx#+xoff,tsy#+yoff,tsx#+x+xoff,tsy#+y+yoff
    next a
    tsx#=tsx#+tsxp#
    tsy#=tsy#+tsyp#
    if tsx#<-xoff or tsx#>xoff or tsy#<-yoff or tsy#>yoff
      target_shoot=0
      tsx#=0.0
      tsy#=0.0
    endif
  endif
endfunction
function draw_target(a#)
  if target=0
    ink rgb(255,255,255),0
    nosex#=cos(a#)*20.0
    nosey#=sin(a#)*20.0
    leftwingx#=cos(a#+225)*20.0
    leftwingy#=sin(a#+225)*20.0
    rightwingx#=cos(a#+135)*20.0
    rightwingy#=sin(a#+135)*20.0
    line nosex#+xoff,nosey#+yoff,leftwingx#+xoff,leftwingy#+yoff
    line nosex#+xoff,nosey#+yoff,rightwingx#+xoff,rightwingy#+yoff
    line leftwingx#+xoff,leftwingy#+yoff,x#+xoff,y#+yoff
    line rightwingx#+xoff,rightwingy#+yoff,x#+xoff,y#+yoff
  else
    ink rgb(t_c,t_c,t_c),0
    for i=1 to 50
      dot tx#(i)+xoff,ty#(i)+yoff
      tx#(i)=tx#(i)+txp#(i)
      ty#(i)=ty#(i)+typ#(i)
    next i
    circle xoff,yoff,int(256-t_c)/2
    ink rgb(t_c,0,0),0
    circle xoff,yoff,256-t_c
    dec t_c
    if t_c=0
      inc level
      gosub reset_target
    endif
  endif
endfunction
function draw_chasers()
  for x=1 to chasers
    if c_a(x)=1
      if c_d(x)=0
        line cx#(x)+xoff-5,cy#(x)+yoff,cx#(x)+xoff+5,cy#(x)+yoff
        line cx#(x)+xoff,cy#(x)+yoff-5,cx#(x)+xoff,cy#(x)+yoff+5
        a#=atan((ship_y#-cy#(x))/(ship_x#-cx#(x)))
        if (ship_x#-cx#(x))<0.0 then a#=a#+180.0
        cxp#(x)=cxp#(x)+cos(a#)*0.1
        cyp#(x)=cyp#(x)+sin(a#)*0.1
        if abs(cxp#(x))>(level/8.0) then cxp#(x)=cxp#(x)-cos(a#)*0.1
        if abs(cyp#(x))>(level/8.0) then cyp#(x)=cyp#(x)-sin(a#)*0.1
        cx#(x)=cx#(x)+cxp#(x)
        cy#(x)=cy#(x)+cyp#(x)
        radius#=sqrt((cx#(x)-ship_x#)^2+(cy#(x)-ship_y#)^2)
        if radius#<10.0
          c_a(x)=0
          explode_ship()
        endif
      else
        dec c_d(x)
        if c_d(x)<0 then c_d(x)=0
      endif
    else
      if x<level-1
        c_a(x)=1
        c_d(x)=x*200
        cx#(x)=0.0
        cy#(x)=0.0
      endif
    endif
  next x
endfunction
function draw_ship(x#,y#,a#)
  if ship=0
    ink rgb(255,255,255),0
    nosex#=cos(a#)*10.0+x#
    nosey#=sin(a#)*10.0+y#
    leftwingx#=cos(a#+225)*10.0+x#
    leftwingy#=sin(a#+225)*10.0+y#
    rightwingx#=cos(a#+135)*10.0+x#
    rightwingy#=sin(a#+135)*10.0+y#
    line nosex#+xoff,nosey#+yoff,leftwingx#+xoff,leftwingy#+yoff
    line nosex#+xoff,nosey#+yoff,rightwingx#+xoff,rightwingy#+yoff
    line leftwingx#+xoff,leftwingy#+yoff,x#+xoff,y#+yoff
    line rightwingx#+xoff,rightwingy#+yoff,x#+xoff,y#+yoff
    if shipfield=1
      ink rgb(shipfieldp,shipfieldp,shipfieldp),0
      circle x#+xoff,y#+yoff,12
    endif
  else
    ink rgb(0,0,s_c),0
    for i=1 to 50
      dot sx#(i)+xoff,sy#(i)+yoff
      sx#(i)=sx#(i)+sxp#(i)
      sy#(i)=sy#(i)+syp#(i)
    next i
    dec s_c
    if s_c=0
      dec ships
      gosub reset_ship
    endif
  endif
endfunction
function draw_forcefield()
  for x=0 to 2
    piece=0
    for y=0 to 11
      if forcefield(x,y)>0
        if forcefield(x,y)=2 then ink rgb(0,128,0),0
        if forcefield(x,y)=1 then ink rgb(128,255,128),0
        inc piece
        step_angle#=angle#(x)+y*30.0
        xpos=cos(step_angle#)*(shell(x)+rad)
        ypos=sin(step_angle#)*(shell(x)+rad)
        newxpos=cos(step_angle#+30)*(shell(x)+rad)
        newypos=sin(step_angle#+30)*(shell(x)+rad)
        line xpos+xoff,ypos+yoff,newxpos+xoff,newypos+yoff
      endif
    next y
    angle#(x)=angle#(x)+(3-x)/5.0
    if angle#(x)>360.0 then angle#(x)=angle#(x)-360.0
    if shell(x)<shell_top(x) then inc shell(x)
    if piece=0
      select x
        case 0
          for y=0 to 11
            forcefield(x,y)=1
          next y
        endcase
        case 1
          for y=0 to 11
            forcefield(x,y)=forcefield(0,y)
            forcefield(0,y)=1
          next y
          shell(x)=0
          shell(0)=-20
        endcase
        case 2
          for y=0 to 11
            forcefield(x,y)=forcefield(1,y)
            forcefield(1,y)=forcefield(0,y)
            forcefield(0,y)=2
          next y
          shell(x)=20
          shell(1)=0
          shell(0)=-20
        endcase
      endselect
    endif
  next x
endfunction
function game_over()
  ink rgb(255,0,0),0
  for char=1 to 8
    read num
    for x=1 to num
      read xpos,ypos,xpos2,ypos2
      line xpos+xoff,ypos+yoff,xpos2+xoff,ypos2+yoff
    next x
  next char
  data 5,-110,-30,-130,-30,-130,-30,-130,30,-130,30,-110,30,-110,30,-110,0,-110,0,-115,0
  data 4,-100,30,-100,-30,-100,-30,-80,-30,-80,-30,-80,30,-80,0,-100,0
  data 4,-70,30,-70,-30,-70,-30,-60,0,-60,0,-50,-30,-50,-30,-50,30
  data 4,-20,-30,-40,-30,-40,-30,-40,30,-40,30,-20,30,-40,0,-30,0
  data 4,10,-30,30,-30,30,-30,30,30,30,30,10,30,10,30,10,-30
  data 4,40,-30,40,0,40,0,50,30,50,30,60,0,60,0,60,-30
  data 4,90,-30,70,-30,70,-30,70,30,70,30,90,30,70,0,80,0
  data 5,100,30,100,-30,100,-30,120,-30,120,-30,120,0,120,0,100,0,100,0,120,30
  set cursor xoff-100,yoff+100
  print "  LEVEL ATTAINED : ";level
  sync
  wait key
endfunction
function make_sound(number)
  format as dword
  channels as dword
  sampleRate as dword
  adr as dword
  chunkSize as dword
  sampleSize as dword
  dword7 as dword
  format = 1
  channels = 1
  sampleRate = 22050
  sampleSize = 16
  chunkSize = (int(sampleSize / 8.0+0.5))*channels
  adr = sampleRate*chunkSize
  dword7 = 0
  select number
    case 1
      length = 75
      wave#=0.1
      increment#=2.0
      gain#=0.1
      amplitude=32000
      decay=120
      speed=sampleRate
    endcase
    case 2
      length=600
      wave#=0.5
      increment#=2.0
      gain#=-0.001
      amplitude=40000
      decay=5
      speed=sampleRate
    endcase
    case 3
      length=2000
      wave#=0.0
      increment#=10.0
      gain#=0.05
      amplitude=65535
      decay=0
      speed = sampleRate
    endcase
    case 4
      length=4000
      wave#=0.0
      increment#=-1.0
      gain#=0.0
      amplitude=65000
      decay=1
      speed = sampleRate
    endcase
  endselect
  rem number of samples
  samples = length*sampleRate/1000
  rem size of memblock
  size = samples*int(sampleSize/8.0+0.5) + 28
  make memblock 1, size
  write memblock dword 1, 0, format
  write memblock dword 1, 4, channels
  write memblock dword 1, 8, sampleRate
  write memblock dword 1, 12, adr
  write memblock dword 1, 16, chunkSize
  write memblock dword 1, 20, sampleSize
  write memblock dword 1, 24, dword7
  pos = 28
  out as word
  for i = 1 to samples
      out = sin(wave#)*amplitude
      write memblock word 1, pos, out
      inc pos, 2
      wave#=wave#+increment#
      if wave#>360.0
        wave#=wave#-360.0
        increment#=increment#-gain#
      endif
      amplitude=amplitude-decay
  next i
  make sound from memblock number,1
  delete memblock 1
  set sound speed number,speed
endfunction
function instructions()
  while not returnkey()
    ink rgb(255,0,0),0
    text 100,100,"INSTRUCTIONS"
    text 100,120,"Left/Right arrow keys - rotate ship"
    text 100,140,"Up arrow - thrust ship"
    text 100,160,"SPACE - fire"
    text 100,180,"Ctrl - shields"
    text 100,220,"OBJECT"
    text 100,240,"Knock out force shields and shoot central ship."
    text 100,260,"Central ship will fire at you when it has a clear shot through the shields"
    text 100,280,"Central ship will re-generate shields when all segments of a shield layer are knocked out"
    text 100,300,"Your shields will deplete with use, and when hit"
    text 100,320,"Watch out for chasers"
    text 100,350,"Press ENTER to start game"
    sync
  endwhile
endfunction