      subroutine strek_find_free_ob (object, first, free_ob, found)
c
c
c    *******************************************************************
c    *****                                                         *****
c    *****                STAR TREK VERSION 3.0                    *****
c    *****                                                         *****
c    *****                     written by                          *****
c    *****                                                         *****
c    *****                Justin S. Revenaugh                      *****
c    *****                                                         *****
c    *****                       7/87                              *****
c    *****                                                         *****
c    *****        Massachussetts Institute of Technology           *****
c    *****  Department of Earth, Atmospheric and Planetary Science *****
c    *****                                                         *****
c    *******************************************************************

c    STREK_FIND_FREE_OB finds a free (unused) object number within
c    the range [first, first+2]. If no such object exists then
c    found is false. Used for finding free photon objects numbers.
c
c
      integer*4 first, free_ob
      logical object(0:9), found
c
c    find first free object
c
      found = .false.
      if (.not.object(first)) then
        found = .true.
        free_ob = first
      else if (.not.object(first+1)) then
        found = .true.
        free_ob = first + 1
      else if (.not.object(first+2)) then
        found = .true.
        free_ob = first + 2
      end if
      return
      end





      subroutine strek_place_nemian (xc, yc, zc, obx, oby, obz, oazm,
     &                               oangle, ospeed, seed)
c
c    STREK_PLACE_NEMIAN places a nubian freighter ship near
c    the players ship. It will always fall in the distance
c    range 600 - 1000.
c
c    version 1
c                                          -jsr 8/85
c
      real*4 xc, yc, zc, obx, oby, obz, ospeed, oazm, oangle
      real*4 seed, radius, theta, phi
      real*4 pi
      save pi
      data pi / 3.14159265/
c
c    find azm and angle totally at random
c
      call rand (seed)
      oazm = pi * seed
      call rand (seed)
      oangle = pi * seed
c
c    find displacement using spherical coordinate geometry
c
      call rand (seed)
      radius = 400.0 * seed + 600.0
      call rand (seed)
      theta = 2.0 * pi * seed
      call rand (seed)
      phi = pi * seed
      sp  = sin(phi)
      obx = radius * cos(theta) * sp + xc
      oby = radius * sin(theta) * sp + yc
      obz = radius * cos(phi)        + zc    
c
c    pick a speed at random
c      
      call rand (seed)
      ospeed = 0.25 + seed * 0.15
      return
      end





      subroutine strek_place_enemy (xc, yc, zc, obx, oby, obz, oazm,
     &                              oangle, ospeed, seed)
c
c    STREK_PLACE_ENEMY places a single enemy ship in the vicinity of
c    the player ship. Initial azm and angle are random.
c
c    version 1
c                                             -jsr 8/85
c
      real*4 xc, yc, zc, obx, oby, obz, oazm, oangle, ospeed
      real*4 seed, radius, theta, phi, pi
      save pi
      data pi / 3.14159265/
c
c    find displacement
c
      call rand (seed)
      radius = 600.0 * seed + 1000.0
      call rand (seed)
      theta = 2.0 * pi * seed
      call rand (seed)
      phi = pi * seed
      sp = sin(phi)
      obx = radius * cos(theta) * sp + xc
      oby = radius * sin(theta) * sp + yc
      obz = radius * cos(phi)        + zc    
      call rand (seed)
      oazm = 2.0 * pi * seed
      call rand (seed)
      oangle = pi * seed
      call rand (seed)
      ospeed = 3.5 * seed
      return
      end






      subroutine strek_enemy_setup (damage, agr, kling, maxd, object,
     &                              seed, two, photons)
c
c    STREK_ENEMY_SETUP initializes many of the enemy ship variables
c    Ensures that there is only one klingon at a time.
c
c    version 1
c                                              -jsr 8/85
c
      integer*4 photons(3)
      real*4 damage(0:9), maxd(9), seed
      logical object(0:9), kling(3), agr(3), two
c
c    set 'em up
c
      i = 2
      j = 3
c
c    set initial damage to zero
c
      damage(i) = 0.0
      damage(j) = 0.0
      photons(i) = 3
      photons(j) = 3
c
c    pick aggression level. Aggressive enemies come after the player
c    ship. Unaggressive enemies shoot nemians
c
      agr(i) = .true.
      agr(j) = .true.
      call rand (seed)
      if (seed.gt.0.90) agr(i) = .false.
      call rand (seed)
      if (seed.gt.0.90) agr(j) = .false.
      call rand (seed)
c
c    check for klingons
c
      call rand (seed)
      if (seed.ge.0.5) then
        kling(i) = .true.
        maxd(i)  = 50.0
      else
        kling(i) = .false.
        kling(j) = .false.
        maxd(i)  = 40.0
        maxd(j)  = 40.0
      end if
c
c    determine the number of 'em
c
      call rand (seed)
      if (seed.gt.0.5) then
        two = .true.
        object(i) = .true.
        object(j) = .true.
      else
        two = .false.
        object(i) = .true.
        object(j) = .false.
      end if         
      if (kling(i)) then
        two = .false.
        object(j) = .false.
      end if
      return
      end





      subroutine strek_move_enemy (j, obx, oby, obz, oazm, oangle,
     &                             ospeed, xc, yc, zc, azm, angle,
     &                             speed, agr, object, rox, roy, roz,
     &                             odamage, photons, distance, kling,
     &                             count_m, count_s, orange, razm, 
     &                             rangle, brake, damage, photon_c,
     &                             phase_c, pro_x, pro_y, seed, pcen)
c
c    STREK_MOVE_ENEMY contains the enemy ship movement and attack
c    logic. When chasing nemians (which is rare) there is only a
c    chase algorithm. When chasing player ships there are two
c    modes: 1. similar to chasing nemians, used when not in ships
c    firing arc or at a distance. 2. randomly choosen dodges which
c    can be: stop fast, accelerate, turn hard or a combination. 
c    Movement is recalculated every 10 turn. Attacks are based on
c    range and the same firing limitations as the player ship, i.e.
c    target in firing arc, in range and phasers active. Photons
c    follow the course of the ship when shot.
c
c    version 1
c                                      - jsr 8/85
c
      integer*2 pcen(2)
      integer*4 photons, j, count_m, count_s, free, photon_c(6)
      integer*4 phase_c
      real*4 obx(0:9), oby(0:9), obz(0:9), oangle(0:9), oazm(0:9)
      real*4 ospeed(0:9), xc, yc, zc, azm, angle, speed, rox, pi
      real*4 roy, roz, odamage(0:9), distance(3,0:9), orange(0:9)
      real*4 pro_x(0:9), pro_y(0:9)
      logical kling, agr, object(0:9), man_1, man_2, found, shoot
      logical man_3
      save pi
      data pi /3.14159265/
      ra(x) = x * pi / 180.0
c
c    increment move and shoot counters
c
      count_m = count_m + 1
      count_s = count_s + 1
c
c    if a move is indicated then do it
c
      if (count_m.ge.10) then
        count_m = 0
        if ((.not.agr).and.(orange(j).gt.90000.0)) then
c
c    chase the nemian unless the bad guy is too close
c
          if (abs(ospeed(j)).gt.1.e-3) then
            num_forward = sqrt(distance(j,1))/ospeed(j)
          else 
            num_forward = 20
          end if
          xt = - num_forward * ospeed(1) * sin(oazm(1)) * cos(oangle(1))
     &         + obx(1)
          yt   = num_forward * ospeed(1) * cos(oazm(1)) * cos(oangle(1))
     &         + oby(1)
          zt   = num_forward * ospeed(1) * sin(oangle(1)) + obz(1)
          dx = xt - obx(j)
          dy = yt - oby(j)
          dz = zt - obz(j)
          if (abs(dy).lt.1.e-7) dy = sign(1.e-7, dy)
          if (dy.le.0.0) then
            tazm = - atan(dx/dy) + ra(180.0)
          else
            tazm = - atan(dx/dy) 
          end if
          dist = sqrt(dx**2 + dy**2)
          if (abs(dist).lt.1.e-7) dist = sign(1.e-7, dist)
          tangle = atan(dz/dist)             
          t1 = (tazm - oazm(j))/10.0
          t2 = (tangle - oangle(j))/10.0
          t3 = (tazm - (oazm(j) - 360.0))/10.0
          t4 = (tangle - (oangle(j) - 360.0))/10.0
          if (abs(t3).lt.abs(t1)) t1 = t3
          if (abs(t4).lt.abs(t2)) t2 = t4
          if (abs(t1).gt.0.05) t1 = sign(.05, t1)
          if (abs(t2).gt.0.05) t2 = sign(.05, t2)         
          razm = t1
          rangle = t2
c
c    adjust speed
c
          if (distance(j,1).gt.3600.0) then
            brake = (3.5 - ospeed(j))/10.0
          else
            brake = (ospeed(1) - ospeed(j) + 0.5)/10.0
          end if
c
c    adjust max acceleration
c
          t1 = abs(brake)
          if (t1.gt.0.5) brake = sign (0.5, brake)
        else
c
c    chase the bad guy. Two options here:
c    1. in his front arc => get out of it!
c    2. in his rear arc  => stay in it but approach.
c
          t1 = sqrt(rox**2 + roz**2)
          t2 = t1 / roy
          if ((((roy.gt.0.0).and.(roy.lt.300.0)).and.(t2.lt.0.75)).or.
     &       (((roy.gt.0.0).and.(roy.lt.820.0)).and.(t2.lt.0.18))) then
            call rand (seed)
c
c    if seed < .10 then brake hard, .10 < seed < .25 then swerve
c    if .25 < seed < .50 then do both, .40 < seed < .60 then accel
c    else actively pursue.
c
            if (seed.lt.0.10) then
              man_1 = .true.
              man_2 = .false.
              man_3 = .false.
            else if ((seed.lt.0.30).and.(seed.ge.0.10)) then
              man_1 = .false.
              man_2 = .true. 
              man_3 = .false.
            else if ((seed.lt.0.50).and.(seed.ge.0.30)) then
              man_1 = .true.
              man_2 = .true. 
              man_3 = .false.
            else if ((seed.lt.0.60).and.(seed.ge.0.50)) then 
              man_1 = .false.
              man_2 = .false.
              man_3 = .true.
            else if (t2.gt.0.33) then
              goto 10
            else
              man_1 = .true.
              man_2 = .true. 
              man_3 = .false.
            end if
            if (man_1.and.((speed.gt.3.5).and.(roy.lt.75.0))) then
              brake = (0.0 - ospeed(j))/10.0
            end if
            if (man_2) then
c
c     get polarity of the swerve
c
              call rand (seed)
              razm = 0.0
              rangle = 0.0
              if (seed.lt.0.25) then
                razm = ra(-3.5)
              else if ((seed.ge.0.25).and.(seed.lt.0.5)) then
                razm = ra(3.5)
              else if ((seed.ge.0.5).and.(seed.lt.0.75)) then
                rangle = ra(-3.5)
              else 
                rangle = ra(3.5)
              end if
            end if
c
c     if man_3 then accelerate
c
            if (man_3) then
              brake = (3.5 - ospeed(j))/10.0
            end if
          else
 10         continue
c
c     in rear arc then pursue
c
            rootor = sqrt(orange(j))
            num_forward = sqrt(orange(j)) / 20.0 
            if (num_forward .gt. 20) num_forward = 20
            xt = - num_forward * speed * sin(ra(azm)) * cos(ra(angle))
     &           + xc
            yt   = num_forward * speed * cos(ra(azm)) * cos(ra(angle))
     &           + yc
            zt   = num_forward * speed * sin(ra(angle)) + zc
            dx = xt - obx(j)
            dy = yt - oby(j)
            dz = zt - obz(j)
           if (abs(dy).lt.1.e-7) dy = sign(1.e-7, dy)
           if (dy.le.0.0) then
             tazm = - atan(dx/dy) + pi
           else
             tazm = - atan(dx/dy) 
           end if
           dist = sqrt(dx**2 + dy**2)
           if (abs(dist).lt.1.e-7) dist = sign(1.e-7, dist)
           tangle = atan(dz/dist)             
c
c    pick smallest angle (needed due to arctan being only in quads 
c    I and IV)
c
           t1 = (tazm - oazm(j))/10.0
           t2 = (tangle - oangle(j))/10.0
           t3 = (tazm - (oazm(j) - 360.0))/10.0
           t4 = (tangle - (oangle(j) - 360.0))/10.0
           if (abs(t3).lt.abs(t1)) t1 = t3
           if (abs(t4).lt.abs(t2)) t2 = t4
           if (abs(t1).gt.0.1) t1 = sign(.1, t1)
           if (abs(t2).gt.0.1) t2 = sign(.1, t2)            
           razm = t1
           rangle = t2
c
c    adjust speed
c
           if (distance(j,1).gt.10000.0) then
             brake = (4.00 - ospeed(j))/10.0
           else
             brake = (speed - ospeed(j) + 0.75)/10.0
           end if
c
c    adjust max acceleration
c
           t1 = abs(brake)
           if (t1.gt.0.5) brake = sign (0.5, brake)
          end if
        end if
      end if
c
c    formulate attacks
c
      if (count_s.ge.20) then
        count_s = 0
c
c    check for photon firing
c
        if (kling) then
          if ((photons.gt.0).and.orange(j).lt.102400) then
            call strek_find_free_ob (object, 4, free, found)
            if (found) then
              t1 = ra(azm)
              t2 = ra(angle)
              call strek_aim_photons (xc, yc, zc, t1, t2, speed,
     &                                obx(j), oby(j), obz(j), oazm(j),
     &                                oangle(j), shoot)
              call rand (seed)
              if (seed.lt.0.7) then
                if (shoot) then
                  object(free) = .true.
                  ospeed(free) = 11.0
                  obx(free)    = obx(j)
                  oby(free)    = oby(j)
                  obz(free)    = obz(j)
                  oazm(free)   = oazm(j)
                  oangle(free) = oangle(j)
                  odamage(free)= 0.0
                  photon_c(free-3) = 0
                  photons = photons - 1
                end if
              end if
            end if
          end if
c
c    if ship is a klingon then consider phasers
c
          if (phase_c.gt.40.0.and.orange(j).lt.40000.0) then
            xt = xc - obx(j)
            yt = yc - oby(j)
            zt = zc - obz(j)
            ca = cos(oazm(j))
            sa = sin(oazm(j))
            cp = cos(oangle(j))
            sp = sin(oangle(j))
            pox =  xt*ca    + yt*sa
            poy = -xt*sa*cp + yt*ca*cp + zt*sp
            poz =  xt*sa*sp - yt*ca*sp + zt*cp            
            if (poy.gt.1.e-7) then
              t1 = pox/poy
              t2 = poz/poy
              if ((t1.lt.1.0).and.(t2.lt.1.0)) then
                call rand (seed)
                if (seed.gt.0.2) then
                  call strek_phaser_damage (orange(j), damage, seed,
     &                                     .true.)
                  call strek_phaser_ship (pro_x(j), pro_y(j), pcen,
     &                                    seed)
                  phase_c = 0
                end if
              end if
            end if
          else if (.not.agr.and.(phase_c.gt.60.0.and.distance(j,1).lt.
     &             10000.0)) then
            xt = obx(1) - obx(j)
            yt = oby(1) - oby(j)
            zt = obz(1) - obz(j)
            ca = cos(oazm(j))
            sa = sin(oazm(j))
            cp = cos(oangle(j))
            sp = sin(oangle(j))
            pox =  xt*ca    + yt*sa
            poy = -xt*sa*cp + yt*ca*cp + zt*sp
            poz =  xt*sa*sp - yt*ca*sp + zt*cp            
            if (poy.gt.1.e-7) then
              t1 = pox/poy
              t2 = poz/poy
              if ((t1.lt.1.0).and.(t2.lt.1.0)) then
                call rand (seed)
                if (seed.gt.0.6) then
                  call strek_phaser_damage (distance(j,1), odamage(1),
     &                                      seed, .false.)
                  call strek_phaser_nemian (pro_x, pro_y)
                  phase_c = 0
                end if
              end if
            end if
          end if
        else
c
c    this is a romulan, either photon player or nemian
c
          if ((photons.gt.0).and.orange(j).lt.90000) then
            call strek_find_free_ob (object, 4, free, found)
            if (found) then
              t1 = ra(azm)
              t2 = ra(angle)
              call strek_aim_photons (xc, yc, zc, t1, t2, speed,
     &                                obx(j), oby(j), obz(j), oazm(j),
     &                                oangle(j), shoot)
              call rand (seed)
              if (seed.lt.0.5) then
                if (shoot) then
                  object(free) = .true.
                  ospeed(free) = 11.0
                  obx(free)    = obx(j)
                  oby(free)    = oby(j)
                  obz(free)    = obz(j)
                  oazm(free)   = oazm(j)
                  oangle(free) = oangle(j)
                  odamage(free)= 0.0
                  photon_c(free-3) = 0
                end if
              end if
            end if
          else if (distance(j,1).lt.40000.0) then
            call strek_find_free_ob (object, 4, free, found)
            if (found) then
              call strek_aim_photons (obx(1), oby(1), obz(1), oazm(1),
     &                                oangle(1), ospeed(1), obx(j),
     &                                oby(j), obz(j), oazm(j),
     &                                oangle(j), shoot)
              call rand (seed)
              if (seed.lt.0.4) then
                if (shoot) then
                  object(free) = .true.
                  ospeed(free) = 11.0
                  obx(free)    = obx(j)
                  oby(free)    = oby(j)
                  obz(free)    = obz(j)
                  oazm(free)   = oazm(j)
                  oangle(free) = oangle(j)
                  odamage(free)= 0.0
                  photon_c(free-3) = 0
                end if
              end if
            end if
          end if
        end if
      end if
c
c    adjust angles and stuff
c
      ospeed(j) = ospeed(j) + brake
      if (ospeed(j).gt.4.00) ospeed(j) = 4.00
      if (ospeed(j).lt.0.0) ospeed(j) = 0.1
      oazm(j) = oazm(j) + razm
      oangle(j) = oangle(j) + rangle
      phase_c = phase_c + 1
      return
      end




      subroutine strek_aim_photons (xc, yc, zc, azm, angle, speed, obx,
     &                              oby, obz, oazm, oangle, shoot)
c
c    STREK_AIM_PHOTONS projects the enemy photons, shoot is true if 
c    the projection falls within 40 units of the projected player
c    ship. Photons do not inherit the parents ship's velocity.
c
c    version 1
c                                  -jsr 8/85
c
      real*4 xc, yc, zc, azm, angle, speed, obx, oby, obz, oazm, oangle
      real*4 pi, a, b, c, oa, ob, oc
      logical shoot
c
c    figure all pertinent angles (note that ship angles are converted
c    to radians in STREK_MOVE_ENEMY).
c
      sa = sin(azm)
      ca = cos(azm)
      sp = sin(angle)
      cp = cos(angle)
      a  = -sa * cp * speed
      b  =  ca * cp * speed
      c  =  sp * speed
      sa = sin(oazm)
      ca = cos(oazm)
      sp = sin(oangle)
      cp = cos(oangle)
      ospeed = 11.0
      oa = -sa * cp * ospeed
      ob =  ca * cp * ospeed
      oc =  sp * ospeed
      da = a - oa
      db = b - ob
      dc = c - oc
      dx = xc - obx
      dy = yc - oby
      dz = zc - obz
c
c    check for an intersection within tolerance (which is 40**2 in
c    an all out attempt not to do sqrt's)
c
      tol = 30.0**2
      shoot = .false.
      j = 1
 10   continue
      if (j.gt.50) return
      dist = (j*(da) + dx)**2 + (j*(db) + dy)**2 + (j*(dc) + dz)**2
      if (dist.le.tol) then
        shoot = .true.
        return
      end if
      j = j + 1
      goto 10
      end 




