home *** CD-ROM | disk | FTP | other *** search
/ Flight Simulators / FLIGHTSIM.ISO / games / wingcomm / brains.c next >
Text File  |  1995-09-07  |  30KB  |  1,243 lines

  1. /*
  2.   ==========================================================================
  3.   |                                WINGLEADER                                                    |
  4.   |                    The 3D space combar simulator                                        |
  5.   |                                                                                                |
  6.   |                A game of interstellar fighter conflict.                            |
  7.   |                                                                                                |
  8.   |         (c)1989,1990 Chris Roberts.  All rights reserved.                        |
  9.   ==========================================================================
  10.  
  11.                         ** NPC PILOT INTELLIGENCE CODE MODULE **
  12. */
  13.  
  14. // #define PCI_DEBUG
  15.  
  16. #define DEBUG_BEGIN  if(DEBUG_INFO!=off){select_text_window(&main_screen);
  17. #define DEBUG_END     }
  18.  
  19. #include <game.h>
  20.  
  21. extern change_mission_type (int obj, objectives new_obj);
  22.  
  23. /*-------------------------------------------------------------------------*/
  24.  
  25. #define DETERMINATION (70-max(0,min(fanatical,pilot_level[obj]))*20)
  26. /*
  27. ------------------------------------------------------------------------------
  28.     coming_home()
  29. ------------------------------------------------------------------------------
  30. */
  31.  
  32. #define NEAR_NAV  (700)
  33. #define NEAR_BASE (2000)
  34.  
  35. void cruise_home(int obj)
  36. {
  37.     int range;
  38.  
  39.     if( abandoned(obj,your_ship) )
  40.         return;
  41.  
  42.     if ((ship_turn[obj]&7) == 5)
  43.         {
  44.         if (no_goal(obj))
  45.             point_ship_at_point(obj,&destination[obj]);
  46.  
  47.         range = distance_from_point(obj,&destination[obj]);
  48.  
  49.         if (equ_vector(&destination[obj],&ship_mission_spot[obj]))
  50.             {
  51.             if( range<NEAR_BASE )
  52.                 {
  53.                 reset_tactic(obj,head_home);
  54.  
  55.                 set_special(obj,kill_engines);
  56.                 zero_vector(&velocity_vec[obj]);
  57.  
  58.                 MissionShips[ship_list_index[obj]].Status = SHIP_PARK;
  59.                 }
  60.             }
  61.         else
  62.             if( range<NEAR_NAV )
  63.                 {
  64.                 visit(Flight_path[ship_tmp_index[obj]]);
  65.                 get_follow_point(obj,&destination[obj]);
  66.                 }
  67.  
  68.         }
  69.  
  70. }
  71.  
  72. void fail(int obj)
  73. {
  74.     report("      => Failure in #%d",obj);
  75. }
  76.  
  77. void coming_home (int obj)
  78. {
  79.     switch( ship_tactic[obj] )
  80.         {
  81.         case cruise: cruise_home(obj); break;
  82.         case head_home:
  83.             if (no_goal(obj))
  84.                 point_parallel(obj,find_ship_index(MissionInfo.Carrier));
  85.             break;
  86.         case NONE:
  87.             reset_tactic(obj,cruise);
  88.             get_first_follow_point(obj,&destination[obj]);
  89.             break;
  90.         default: fail(obj);
  91.         }
  92. }
  93.  
  94. /*
  95. ------------------------------------------------------------------------------
  96.     run_away()
  97. ------------------------------------------------------------------------------
  98. */
  99.  
  100. run_away (int obj)
  101. {
  102.  vec_3D vec;
  103.  #define ROUT_RANGE  (16000)
  104.  
  105.      if (isactive(ship_wingleader[obj]))
  106.          if (ship_mission_type[ship_wingleader[obj]] == rout)
  107.             {
  108.             maintain_formation(obj);
  109.             return;
  110.             }
  111.  
  112.     if (side[obj] == Imperial)
  113.         coming_home(obj);
  114.     else
  115.         {
  116.         // All Kilrathi flee straight down.
  117.         zero_vector(&vec);
  118.         vec.y = IntFract(1);
  119.         if (obj&1)
  120.             vec.y = -vec.y;
  121.  
  122.         point_ship(obj,0,&vec);
  123.  
  124.         if( normal_speed(obj) && random(100)<5 )
  125.             fire_afterburner(obj,STD_BURN*2);
  126.         else
  127.             approach_full_speed(obj);
  128.         // This really ought to do some dodging maneuvers during the rout. -KLD
  129.  
  130.         // WARNING: is this remove_object() good enough to kick ship shapes out
  131.         // if necessary?? -RKLD
  132.         if (distance_from_object(obj,your_ship) > ROUT_RANGE)
  133.             remove_object(obj);
  134.         }
  135.  
  136. }
  137.  
  138.  
  139. /*
  140. ------------------------------------------------------------------------------
  141. */
  142.  
  143.  
  144. int check_engage_target(int obj)        // for combat in general...
  145. {
  146.  int new_target;
  147.  
  148.      if( (new_target=detect_enemy_tail(obj)) != NONE && new_target!=ship_target[obj] )
  149.         ship_target[obj] = new_target;
  150.     else
  151.         if( !target_valid(obj) )
  152.             select_target(obj);
  153.     return( ship_target[obj] );
  154. }
  155.  
  156. int check_destroy_target(int obj)
  157. {
  158.  int destroy_target = find_ship_index(ship_mission_ship[obj]);
  159.  int test_target;
  160.  
  161.     if( class[destroy_target]==futurion || gone_ship(ship_mission_ship[obj]) )
  162.         check_engage_target(obj);
  163.     else
  164.          if( evaluate_damage(obj)>DETERMINATION )
  165.             {
  166.             ship_target[obj] = destroy_target;
  167.             if( side[destroy_target]==side[obj] )
  168.                 warn("KS");
  169.             }
  170.         else
  171.             if( (target_valid(obj) && random(100)>3) )
  172.                 check_engage_target(obj);
  173.             else
  174.                 ship_target[obj]=destroy_target;
  175.  
  176.     return( ship_target[obj] );
  177. }
  178.  
  179. void maneuvering(int obj, int new_target)
  180. {
  181.     ship_target[obj] = new_target;
  182.  
  183.     intelligence_events(obj);
  184.  
  185.     perform_maneuver(obj);
  186. }
  187.  
  188.  
  189.  
  190. /*
  191. ------------------------------------------------------------------------------
  192.     formation_burst()
  193. ------------------------------------------------------------------------------
  194. */
  195.  
  196. #define BURST_TIMER  9
  197.  
  198. void formation_burst (int obj)
  199. {
  200.  vec_3D vec;
  201.  int leader = ship_wingleader[obj];
  202.  
  203.     approach_full_speed(obj);
  204.  
  205.     if (no_goal(obj))
  206.         point_ship(obj,0,&destination[obj]);
  207.  
  208.     if (++ship_count[obj] > BURST_TIMER)
  209.         if( ship_mission_type[obj]==strike )
  210.             engage(obj,ship_target[obj],destroy_ship);
  211.         else
  212.             engage(obj,ship_target[obj],engage_enemy);
  213. }
  214.  
  215.  
  216.  
  217. /*
  218. ------------------------------------------------------------------------------
  219.     capital_combat()
  220. ------------------------------------------------------------------------------
  221. */
  222.  
  223. capital_combat (int obj)
  224. {
  225.  
  226. } /* capital_combat() */
  227.  
  228.  
  229. /*
  230. ------------------------------------------------------------------------------
  231.     imperial_formation()
  232. ------------------------------------------------------------------------------
  233. */
  234.  
  235. int enemy_sighting = NO_SIGHTINGS;
  236.  
  237. imperial_formation (int obj)
  238. {
  239.  int leader = ship_wingleader[obj];
  240.  int target;
  241.  vec_3D dest;
  242.  int closest;
  243.  
  244.     maintain_formation(obj);
  245.  
  246. #define THREATENING (11000)
  247. #define VISUAL (14000)
  248.  
  249.     if (attacker_in_range(leader,THREATENING))
  250.         {
  251.         if (auto_engage_timer != NONE)
  252.             if (--auto_engage_timer == 0)
  253.                 allow_engage();
  254.  
  255.         if( allowed_to_engage(obj) )        // target ship is pulled out of the blue! -RKLD
  256.             engage(obj,target_ship,engage_enemy);
  257.         else
  258.             if (obj == your_wingman)
  259.                 if (
  260.                     (ship_turn[obj]&15)==0 &&
  261.                     (auto_engage_timer == NONE)
  262.                     )
  263.                     {
  264.                     send_message(obj, COM_atk_request);
  265.                     auto_engage_timer = 25;
  266.                     }
  267.         }
  268.     else
  269.         {
  270.         if( obj==your_wingman && enemy_sighting!=current_wave && any_enemy(obj,VISUAL) )
  271.             if( !message_showing() && cockpit_view==front )
  272.                 {
  273.                 send_message(obj,COM_i_see_enemy);
  274.                 enemy_sighting = current_wave;
  275.                 }
  276.         }
  277.  
  278. #define FAR_AWAY        (9000)
  279. #define TOWARD            (85)
  280.  
  281.     if (special_maneuver[obj] == NONE)
  282.         if (distance_from_object(obj,leader) > FAR_AWAY)
  283.             if ((facing_to_object(obj,leader) > TOWARD)
  284.             && (real_velocity(obj) < 110 ))
  285.                 fire_afterburner(obj,STD_BURN);
  286.             else
  287.                 {
  288.                 point_ship_at_object(obj,leader);
  289.                 approach_ship_speed(obj,leader);
  290.                 }
  291.  
  292. } /* imperial_formation() */
  293.  
  294.  
  295. /*
  296. ------------------------------------------------------------------------------
  297.     formation_break()
  298. ------------------------------------------------------------------------------
  299. */
  300.  
  301. formation_break (int obj)
  302. {
  303.  
  304. /*
  305.     WHENEVER SOMEBODY DESIGNS THE FORMATIONS SOME SCRIPTS
  306.     WILL HAVE TO BE SET UP FOR THE WINGMEN TO BREAK AWAY
  307.     FROM THE FORMATION IN A VISUALLY EXCITING MANNER...
  308. */
  309.  
  310.     switch (ship_seq[obj])
  311.         {
  312.         case 0:
  313.             steady_object(obj);
  314.             yaw_goal[obj] = -30;
  315.             roll_goal[obj] = -45;
  316.             pitch_goal[obj] = -20;
  317.             ++ship_seq[obj];
  318.             break;
  319.  
  320.         case 1:
  321.             if (no_goal(obj))
  322.                 engage(obj,ship_target[obj],engage_enemy);
  323.             break;
  324.         default: ship_seq[obj] = 0;
  325.         }
  326. }
  327.  
  328.  
  329.  
  330. /*
  331. ------------------------------------------------------------------------------
  332.     imperial_wingman()
  333.         routine for a WINGMAN on the Player's Side on a PATROL mission
  334. ------------------------------------------------------------------------------
  335. */
  336.  
  337. void imperial_wingman (int obj)
  338. {
  339.  int target;
  340.  int leader = ship_wingleader[obj];
  341.  
  342.     switch (ship_objective[obj])
  343.         {
  344.         case hold_formation: imperial_formation(obj); break;
  345.         case break_formation: formation_break(obj); break;
  346.         case engage_enemy: maneuvering(obj,check_engage_target(obj)); break;
  347.         case destroy_ship: maneuvering(obj,check_destroy_target(obj)); break;
  348.         case NONE: reset_objective(obj,hold_formation); break;
  349.         default: fail(obj);
  350.         }
  351. }
  352.  
  353.  
  354. /*
  355. ------------------------------------------------------------------------------
  356.     kilrathi_wingman()
  357. ------------------------------------------------------------------------------
  358. */
  359.  
  360. void kilrathi_wingman(int obj)
  361. {
  362.  int leader = ship_wingleader[obj];
  363.  
  364.     if (leader == NONE)
  365.         {
  366.         change_mission_type(obj,patrol);
  367.         return;
  368.         }
  369.      else
  370.         if( unactive(leader) )
  371.             {
  372.             inherit_leader(obj);
  373.             return;
  374.             }
  375.  
  376.     if( ship_objective[leader]==engage_enemy || ship_objective[leader]==destroy_ship )
  377.         if( ship_objective[obj]!=ship_objective[leader] )
  378.             engage(obj,ship_target[obj],ship_objective[leader]);
  379.  
  380.     switch( ship_objective[obj] )
  381.         {
  382.         case hold_formation:    maintain_formation(obj); break;
  383.         case break_formation: formation_burst(obj); break;
  384.         case destroy_ship:    // protect your wingleader!
  385.         case engage_enemy: maneuvering(obj,check_engage_target(obj)); break;
  386.         case NONE: reset_objective(obj,hold_formation); break;
  387.         default: fail(obj);
  388.         }
  389.  
  390. }
  391.  
  392.  
  393. /*
  394. ------------------------------------------------------------------------------
  395.     wingman_mission()
  396. ------------------------------------------------------------------------------
  397. */
  398.  
  399. void wingman_mission(int obj)
  400. {
  401.     if( side[obj]==Imperial )
  402.         imperial_wingman(obj);
  403.     else
  404.         kilrathi_wingman(obj);
  405. }
  406.  
  407. /*
  408. ------------------------------------------------------------------------------
  409. */
  410.  
  411. int dist_from_home(int obj)
  412. {
  413.     return( distance_from_point(obj,&ship_mission_spot[obj]) );
  414. }
  415.  
  416. /*
  417. ------------------------------------------------------------------------------
  418.     kilrathi_patrol()
  419. ------------------------------------------------------------------------------
  420. */
  421. #define PATROL_RADIUS (8000)        // when this far out, must get closer.
  422. #define WANDER_RADIUS (3000)        // when this close to patrol pt, can wander.
  423. #define APPROACH_BEHIND (490)
  424. #define NORMAL_SCANNER (14000)
  425. #define APPROACH_RANGE  (10000)        // break form now.
  426.  
  427. int scan_and_lock(int obj, int scan_range, tactics new_tactic)
  428. {
  429.  int new_target;
  430.  
  431.      ship_target[obj] = scan_for_enemy(obj,NORMAL_SCANNER);
  432.     if( ship_target[obj]!=NONE )
  433.         ship_tactic[obj] = new_tactic;
  434.     return( ship_target[obj]!=NONE );
  435. }
  436.  
  437. void patrol_area(int obj)
  438. {
  439.  int target = ship_target[obj];
  440.  unsigned int range;
  441.  vec_3D spot;
  442.  
  443.      switch (ship_tactic[obj])
  444.         {
  445.         case look_out:
  446.             approach_cruise_speed(obj);
  447.             if( !scan_and_lock(obj,NORMAL_SCANNER,approach_target) )
  448.                 if( dist_from_home(obj) > PATROL_RADIUS )
  449.                     reset_tactic(obj,head_home);
  450.             break;
  451.  
  452.         case head_home:
  453.             approach_cruise_speed(obj);
  454.             if( !scan_and_lock(obj,NORMAL_SCANNER,approach_target) )
  455.                 {
  456.                 ship_vs_point(obj,&ship_mission_spot[obj]);
  457.  
  458.                 if( target_range<WANDER_RADIUS )
  459.                     reset_tactic(obj,look_out);
  460.                 else
  461.                     {
  462.                     // what exactly does this do? -KLD
  463.                     point_ship_at_point(obj,&ship_mission_spot[obj]);
  464.                     trim_goals(obj,7);
  465.                     }
  466.                 }
  467.             break;
  468.  
  469.         case approach_target:
  470.             approach_full_speed(obj);
  471.             if( unactive(target) )
  472.                 {
  473.                 if( !scan_and_lock(obj,NORMAL_SCANNER,approach_target) )
  474.                     alter_tactic(obj,look_out);
  475.                 }
  476.             else
  477.                 {
  478.                 ship_vs_ship(obj,target);
  479.  
  480.                 if( target_range<APPROACH_RANGE )
  481.                     init_formation_burst(obj);
  482.                 else
  483.                     if( no_goal(obj) )
  484.                         point_ship_at_object(obj,target);
  485.                 }
  486.             break;
  487.  
  488.         case NONE: reset_tactic(obj,approach_target); break;
  489.         default: fail(obj);
  490.         }
  491. }
  492.  
  493.  
  494.  
  495. void kilrathi_patrol (int obj)
  496. {
  497.     switch( ship_objective[obj] )
  498.         {
  499.         case break_formation: formation_burst(obj); break;
  500.         case hold_formation:
  501.         case wander: patrol_area(obj); break;
  502.         case engage_enemy: maneuvering(obj,check_engage_target(obj)); break;
  503.         case NONE:
  504.             ship_objective[obj] = wander;
  505.             ship_tactic[obj] = approach_target;
  506.             break;
  507.         default: fail(obj);
  508.         }
  509. }
  510.  
  511.  
  512. /*
  513. ------------------------------------------------------------------------------
  514.     imperial_wingleader()
  515. ------------------------------------------------------------------------------
  516. */
  517.  
  518. imperial_wingleader (int obj)
  519. {
  520.     kilrathi_patrol(obj);        // there is no specialized Impeial leader
  521.                                         // intelligence yet... it may not be needed?
  522. } /* imperial_wingleader() */
  523.  
  524.  
  525. /*
  526. ------------------------------------------------------------------------------
  527.     reach_warp()
  528. ------------------------------------------------------------------------------
  529. */
  530.  
  531. #define TOWARD     (65)
  532. void cruise_to_destination(int obj)
  533. {
  534.  int range;
  535.  
  536.     // Don't move if you're too far away:
  537.     if( abandoned(obj,your_ship) ) return;
  538.  
  539.     // Set speed according to presence of enemies:
  540.     if( (ship_turn[obj]&7)==6 )
  541.         ship_target[obj] = scan_for_enemy(obj,CAPITAL_SCANNER_RANGE);
  542.  
  543.     if (ship_target[obj] == NONE)
  544.         approach_cruise_speed(obj);
  545.     else
  546.         {
  547.         get_facing_range_from_object(obj,ship_target[obj]);
  548.  
  549.         if (facing_to_target > TOWARD)
  550.             approach_half_speed(obj);            // slow when approaching enemies.
  551.         else
  552.             approach_full_speed(obj);            // accelerate out from them.
  553.         }
  554.  
  555.     // Check destination:
  556.     if ((ship_turn[obj]&7) == 2)
  557.         {
  558.         if (no_goal(obj))
  559.             point_ship_at_point(obj,&destination[obj]);
  560.  
  561.         range = distance_from_point(obj,&destination[obj]);
  562.  
  563.         if( range < NEAR_NAV )
  564.             {
  565.             flag_reached(Flight_path[ship_tmp_index[obj]]);
  566.             if (equ_vector(&destination[obj],&ship_mission_spot[obj]))
  567.                 {
  568.                 reset_tactic(obj,sit_still);
  569.                 set_special(obj,kill_engines);
  570.                 }
  571.             else
  572.                 get_follow_point(obj,&destination[obj]);
  573.             }
  574.         }
  575. }
  576.  
  577. #define WARP_OUT_RANGE         (4000)
  578. #define PREPARE_WARP_TIMER    10
  579. void prepare_for_jump(int obj)
  580. {
  581.     if( speed[obj]!=0 )
  582.         set_special(obj,stop_drift);
  583.     else
  584.         if (object_nearby(obj,your_ship,WARP_OUT_RANGE))
  585.             if (++ship_count[obj] > PREPARE_WARP_TIMER)
  586.                 {
  587.                 reset_tactic(obj,warp_out);
  588.                 fire_afterburner(obj,STD_BURN);
  589.                 }
  590. }
  591.  
  592. #define ACCELERATION_TIMER    3
  593. void accelerate_and_jump(int obj)
  594. {
  595.     approach_full_speed(obj);
  596.  
  597.     if (ship_count[obj]++ == ACCELERATION_TIMER)
  598.         warp(obj);
  599. }
  600.  
  601. /////////////////////////////////////////////////////
  602. void reach_warp (int obj)
  603. {
  604.     switch (ship_tactic[obj])
  605.         {
  606.         case cruise: cruise_to_destination(obj); break;
  607.         case sit_still: prepare_for_jump(obj); break;
  608.         case warp_out: accelerate_and_jump(obj); break;
  609.         case NONE:
  610.             reset_tactic(obj,cruise);
  611.             get_first_follow_point(obj,&destination[obj]);
  612.             break;
  613.         default: fail(obj);
  614.         }
  615. }
  616.  
  617.  
  618. /*
  619. ------------------------------------------------------------------------------
  620.     warp_arrival()
  621. ------------------------------------------------------------------------------
  622. */
  623.  
  624. void arrive_from_warp(int obj)
  625. {
  626.  int index = find_objective(nav_point,Current_action_sphere);
  627.  
  628.     if (index != NONE)    // Don't really need to go to that Nav Point...
  629.         {
  630.         visit(index);
  631.         if (Current_Objective == index)
  632.             set_next_destination();
  633.         }
  634.  
  635.     unwarp(obj);
  636.     speed[obj] = IntToIntFract(data[type[obj]].max_velocity);
  637.     fix_velocity(obj);
  638.  
  639.     reset_mission_type(obj,patrol);
  640. }
  641.  
  642.  
  643. void warp_arrival(int obj)
  644. {
  645.     if( ship_tactic[obj]==warp_in )
  646.         arrive_from_warp(obj);
  647.     else
  648.         reset_tactic(obj,warp_in);
  649. }
  650.  
  651.  
  652. /*
  653. ------------------------------------------------------------------------------
  654.     escort_mission()
  655. ------------------------------------------------------------------------------
  656. */
  657. #define ESCORT_RESUMED (1000)
  658.  
  659. void return_to_buddy(int obj, int buddy)
  660. {
  661.     approach_cruise_speed(obj);
  662.     if( no_goal(obj) )
  663.         point_ship_at_object(obj,buddy);
  664.     if( distance_from_object(obj,buddy)<ESCORT_RESUMED )
  665.         {
  666.         reset_objective(obj,wander);
  667.         point_parallel(obj,buddy);
  668.         }
  669. }
  670.  
  671. void escort_buddy(int obj, int buddy)
  672. {
  673.     approach_ship_speed(obj,buddy);
  674.     if (no_goal(obj))
  675.         point_parallel(obj,buddy);
  676. }
  677.  
  678. #define ESCORT_DANGER  (3000)
  679. #define ESCORT_DRIFT    (5000)        // This should be more than ESCORT_DANGER
  680. #define ESCORT_RADIUS  (1200)
  681.  
  682. void escort_mission(int obj)
  683. {
  684.  int buddy = find_ship_index(ship_mission_ship[obj]);
  685.  
  686.      if (unactive(buddy))
  687.         {
  688.         change_mission_type(obj,patrol);
  689.         return;
  690.         }
  691.  
  692.     if( !(ship_turn[obj]&3) )
  693.         if( in_danger(buddy) )
  694.             if( target_range < ESCORT_DANGER )
  695.                 engage(obj,target_ship,engage_enemy);
  696.                 
  697.     if (ship_objective[obj] != home_base)
  698.         if( (ship_turn[obj]&7)==4 )
  699.             if (distance_from_object(obj,buddy) > ESCORT_DRIFT)
  700.                 reset_objective(obj,home_base);
  701.  
  702.     switch( ship_objective[obj] )
  703.         {
  704.         case wander: escort_buddy(obj,buddy); break;
  705.         case home_base: return_to_buddy(obj,buddy); break;
  706.         case engage_enemy: maneuvering(obj,check_engage_target(obj)); break;
  707.         case NONE: reset_objective(obj,wander); break;
  708.         default: fail(obj);
  709.         }
  710.  
  711. }
  712.  
  713.  
  714. /*
  715. ------------------------------------------------------------------------------
  716.     strike_mission()
  717. ------------------------------------------------------------------------------
  718. */
  719.  
  720. void check_goal(int obj)
  721. {
  722.  vec_3D xyz;
  723.     if( gone_ship(ship_mission_ship[obj]) )
  724.         reset_mission_type(obj,rout);
  725.     else
  726.         {
  727.         warn("This shouldn't happen!",0);
  728.         locate_ship(ship_mission_ship[obj],&xyz);
  729.         if (no_goal(obj))
  730.             point_ship_at_point(obj,&xyz);
  731.         approach_full_speed(obj);
  732.         }
  733. }
  734.  
  735. void streak_toward(int obj, int goal, int range)
  736. {
  737.     if( no_goal(obj) )
  738.         if( random(100)<95 )
  739.             point_ship_at_object(obj,goal);
  740.         else
  741.             veer_random(obj,20);
  742.  
  743.     if( range>2000 && normal_speed(obj) )
  744.         fire_afterburner(obj,STD_BURN);
  745.     else
  746.         approach_full_speed(obj);
  747. }
  748.  
  749.  
  750.  
  751. #define ENGAGE_RANGE        (5000)        // just a bit shorter than normal...
  752. void approach_and_engage(int obj, int goal)
  753. {
  754.  unsigned int range, possible_range;
  755.  int possible_target;
  756.  
  757.     range = distance_from_object(obj,goal);
  758.      if( class[goal]!=futurion && evaluate_damage(obj)>DETERMINATION && range>ENGAGE_RANGE )
  759.         streak_toward(obj,goal,range);
  760.     else
  761.         {
  762.         possible_target = scan_for_enemy(obj,10000);
  763.         possible_range = target_range;
  764.         if( possible_target!=NONE && (possible_range*3<range || class[goal]==futurion) )
  765.             {
  766.             init_formation_burst(obj);
  767.             ship_target[obj] = possible_target;
  768.             }
  769.         else
  770.             if( range<ENGAGE_RANGE )
  771.                 engage(obj,goal,destroy_ship);
  772.             else
  773.                 streak_toward(obj,goal,range);
  774.             }
  775. }
  776.  
  777. void strike_mission (int obj)
  778. {
  779.  int goal = find_ship_index(ship_mission_ship[obj]);
  780.  
  781.     // Check status of STRIKE objective ship...
  782.     if( goal==NONE && class[goal]!=futurion )
  783.         check_goal(obj);
  784.  
  785.     switch( ship_objective[obj] ) {
  786.         case break_formation: formation_burst(obj); break;
  787.         case hold_formation:
  788.         case home_base: approach_and_engage(obj,goal); break;
  789.         case engage_enemy: maneuvering(obj,check_destroy_target(obj)); break;
  790.         case destroy_ship: maneuvering(obj,check_destroy_target(obj)); break;
  791.         case NONE:reset_objective(obj,home_base); break;
  792.         default: fail(obj);
  793.         }
  794. }
  795.  
  796.  
  797. /*
  798. ------------------------------------------------------------------------------
  799.     defend_mission()
  800. ------------------------------------------------------------------------------
  801. */
  802. #define DEFEND_RADIUS  (6000)
  803. #define DEFEND_RESUMED (5000)        // must be less than the defend radius.
  804.  
  805. void return_to_master(int obj, int master)
  806. {
  807.  int range = distance_from_object(obj,master);
  808.  
  809.     streak_toward(obj,master,range);
  810.  
  811.     if( range<DEFEND_RESUMED )
  812.         {
  813.         reset_objective(obj,wander);
  814.         point_perpendicular(obj,master);
  815.         }
  816. }
  817.  
  818.  
  819. void defend_mission (int obj)
  820. {
  821.  int master = find_ship_index(ship_mission_ship[obj]);
  822.  
  823.     if( master==NONE )
  824.         {
  825.         change_mission_type(obj,patrol);
  826.         return;
  827.         }
  828.  
  829.     if( ship_turn[obj]%10 == 0 )
  830.         if( in_danger(master) )
  831.             if( target_range<DEFEND_RADIUS )
  832.                 {
  833.                 if( ship_objective[obj]!=engage_enemy)
  834.                     engage(obj,target_ship,engage_enemy);
  835.                 }
  836.  
  837.     if( ship_objective[obj]!=home_base )
  838.         if ((ship_turn[obj]&7) == 4)
  839.             if (distance_from_object(obj,master) > 10000)
  840.                 reset_objective(obj,home_base);
  841.  
  842.     switch( ship_objective[obj] )
  843.         {
  844.         case wander:
  845.              ship_target[obj] = scan_for_enemy(obj,7000);
  846.             if( ship_target[obj]!=NONE )
  847.                 engage(obj,ship_target[obj],engage_enemy);
  848.             else
  849.                 {
  850.                 approach_half_speed(obj);
  851.                 if (no_goal(obj))
  852.                     point_perpendicular(obj,master);
  853.                 }
  854.             break;
  855.         case home_base: return_to_master(obj,master); break;
  856.         case engage_enemy: maneuvering(obj,check_engage_target(obj)); break;
  857.         case NONE: reset_objective(obj,wander); break;
  858.         default: fail(obj);
  859.         }
  860. }
  861.  
  862.  
  863. /*
  864. ------------------------------------------------------------------------------
  865.     rendezvous_mission()
  866.  
  867.         RENDEZVOUS missions are for Ships travelling to another Ship, usually
  868.         a Capital Ship, that it will be set to DEFEND as a new mission type...
  869. ------------------------------------------------------------------------------
  870. */
  871.  
  872. rendezvous_mission (int obj)
  873. {
  874.  int goal = find_ship_index(ship_mission_ship[obj]);
  875.  
  876.     if (unactive(goal))
  877.         {
  878.         change_mission_type(obj,patrol);
  879.         return;
  880.         }
  881.  
  882.     switch (ship_objective[obj])
  883.         {
  884.         case (reach_ship):
  885.             if (attacker_in_range(obj,3500))        // only very close attackers
  886.                 engage(obj,target_ship,engage_enemy);
  887.  
  888.             if (IS_NEAR(obj,goal,2500))
  889.                 {
  890.                 reset_mission_type(obj,defend);
  891.                 return;
  892.                 }
  893.         
  894.             if (attacker_in_range(goal,9000))
  895.                 approach_full_speed(obj);
  896.             else
  897.                 approach_cruise_speed(obj);
  898.  
  899.             if (no_goal(obj))
  900.                 point_ship_at_object(obj,goal);
  901.         break;
  902.  
  903.         case (engage_enemy):    maneuvering(obj,check_engage_target(obj)); break;
  904.  
  905.         default:    reset_objective(obj,reach_ship);
  906.         }
  907.  
  908.  
  909. } /* rendezvous_mission() */
  910.  
  911.  
  912. /*
  913. ------------------------------------------------------------------------------
  914.     ship_intelligence()
  915. ------------------------------------------------------------------------------
  916. */
  917.  
  918. void ship_intelligence (int obj)
  919. {
  920.  int target;
  921.  
  922.     if( regulate_turn(obj) ) return;
  923.  
  924.     switch (ship_mission_type[obj])
  925.         {
  926.         case (patrol):
  927.             if( side==Imperial )
  928.                 imperial_wingleader(obj);
  929.             else
  930.                 kilrathi_patrol(obj);
  931.             break;
  932.  
  933.         case (escort):    escort_mission(obj); break;
  934.  
  935.         case (strike):    strike_mission(obj);    break;
  936.  
  937.         case (defend):    defend_mission(obj); break;
  938.  
  939.         case (wingman): wingman_mission(obj); break;
  940.  
  941.         case (rendezvous): rendezvous_mission(obj); break;
  942.  
  943.         case (rout): run_away(obj); break;
  944.  
  945.         case NONE: inherit_leader_mission(obj); break;
  946.  
  947.         default: fail(obj);
  948.         }
  949.  
  950. }
  951.  
  952.  
  953. /*
  954. ------------------------------------------------------------------------------
  955.     capital_ship_intelligence()
  956. ------------------------------------------------------------------------------
  957. */
  958.  
  959. void mega_ship (int obj)  // only used for the ralari. -KLD
  960. {
  961.  int radius = MissionSpheres[Current_action_sphere].Radius>>1;
  962.  vec_3D center = MissionSpheres[Current_action_sphere].Center;
  963.  int range;
  964.  
  965.     if (fire_turrets(obj))
  966.         {
  967.         ship_target[obj] = NONE;
  968.         approach_half_speed(obj);
  969.         }
  970.     else
  971.         approach_cruise_speed(obj);
  972.  
  973.     range = distance_from_point(obj,¢er);
  974.  
  975.     if (no_goal(obj))
  976.         if (range > radius-750)
  977.             if (range > radius)
  978.                 point_ship_at_point(obj,¢er);
  979.             else
  980.                 point_perpendicular_to_point(obj,¢er);
  981.  
  982.     trim_goals(obj,5);
  983.  
  984. } /* mega_ship() */
  985.  
  986.  
  987. void capital_ship_intelligence (int obj)
  988. {
  989.     if (regulate_turn(obj))
  990.         return;
  991.  
  992.     switch (ship_mission_type[obj])
  993.         {
  994.         case goto_warp: reach_warp(obj); break;
  995.  
  996.         case warp_arrive: warp_arrival(obj); break;
  997.  
  998.         case come_home: coming_home(obj); break;
  999.  
  1000.         case rout: run_away(obj); break;
  1001.  
  1002.         case patrol: //  well...?  -KLD
  1003.  
  1004.         default :
  1005.  
  1006.             if (
  1007.                 type[obj] == Ralari ||
  1008.                 type[obj] == Fralthi
  1009.                 )
  1010.                 {
  1011.                 mega_ship(obj);        // just testing for now... (pci)
  1012.                 return;
  1013.                 }
  1014.             
  1015.             if (unactive( target_ship = ship_target[obj] ))
  1016.                 scan_for_enemy(obj,CAPITAL_SCANNER_RANGE);
  1017.  
  1018.             switch (ship_tactic[obj])
  1019.                 {
  1020.                 case (self_defense):
  1021.                     approach_full_speed(obj);
  1022.                     if( unactive(ship_target[obj]) )
  1023.                         {
  1024.                         select_target(obj);
  1025.                         if( unactive(ship_target[obj]) )
  1026.                             reset_tactic(obj,NONE);                // seems reasonable, but... -KLD
  1027.                         }
  1028.                     else
  1029.                         fire_turrets(obj);
  1030.                     break;
  1031.     
  1032.                 default :
  1033.                     //  How would target_ship ever be set to anything here? -KLD
  1034.                     if (target_ship != NONE)
  1035.                         {
  1036.                         approach_full_speed(obj);
  1037.                         ship_tactic[obj] = self_defense;
  1038.                         ship_target[obj] = target_ship;
  1039.                         fire_turrets(obj);
  1040.                         }
  1041.                     else                                              // follow Bee Line in
  1042.                         approach_cruise_speed(obj);        // ship's current dir
  1043.                 }
  1044.  
  1045.         }
  1046.  
  1047. }
  1048.  
  1049. /*
  1050. ------------------------------------------------------------------------------
  1051.     futurion_intelligence()
  1052.  
  1053.         this routine holds off an object from taking on its true
  1054.         class until your_ship is nearby and looking toward it...
  1055.         the proper class should be stored in object_counter[un_obj]
  1056. ------------------------------------------------------------------------------
  1057. */
  1058.  
  1059. futurion_intelligence (int un_obj)
  1060. {
  1061.  #define MUST_ARRIVE 49
  1062.  
  1063.     ship_vs_ship(your_ship,un_obj);                        // Velveteen Rabbit...
  1064.  
  1065.     if ( 
  1066.         (++action_count[un_obj] > MUST_ARRIVE) ||
  1067.         (target_range < 7000) && (facing_to_target > 80)
  1068.         )
  1069.         if (one_in(8))
  1070.             class[un_obj] = object_counter[un_obj];    // become a REAL class
  1071.  
  1072. } /* futurion_intelligence() */
  1073.  
  1074.  
  1075.  
  1076. /*
  1077. ------------------------------------------------------------------------------
  1078.     mine_intelligence()
  1079. ------------------------------------------------------------------------------
  1080. */
  1081.  
  1082. void mine_intelligence (int obj)
  1083. {
  1084.  int target_ship;
  1085.  int distance;
  1086.  
  1087.     if (object_counter[obj] != 0) /* can't explode until active! */
  1088.         return;
  1089.  
  1090.     /*-- Check to see if any ships are in the vincinity of the mine --*/
  1091.     for (target_ship = your_ship; target_ship <= last_ship; target_ship++)
  1092.         {
  1093.         if (obj != target_ship)
  1094.             {
  1095.             if (class[target_ship] == ship)
  1096.                 {
  1097.                 if (distance_from_object(obj, target_ship) < MINE_DETONATION_RANGE)
  1098.                     {
  1099.                     /*-- If ship is too close to mine, it explodes --*/
  1100.                     explode(obj);
  1101.                     return;
  1102.                     }
  1103.                 }
  1104.             }
  1105.         }
  1106. } /* mine_intelligence() */
  1107.  
  1108.  
  1109. /*
  1110. ------------------------------------------------------------------------------
  1111.     heat_seeking_missile_intelligence()
  1112. ------------------------------------------------------------------------------
  1113. */
  1114.  
  1115. void heat_seeking_missile_intelligence (int obj)
  1116. {
  1117.  int exhaust_heat, target_ship, targ;
  1118.  
  1119.     /*--------Intelligence used for heat seeking missiles ---------*/
  1120.  
  1121.     // This is implemented wrong.  Heat seekers need enemy to be facing away... -KLD
  1122.      if (facing_to_target < 0 || ship_target[obj] == NONE)
  1123.         {
  1124.         /*-- If lock is lost on the target, look for closest "hotest" target --*/
  1125.         ship_target[obj] = NONE;
  1126.  
  1127.         viable_target_index = 0;
  1128.         for (target_ship = your_ship; target_ship <= last_ship; target_ship++)
  1129.             {
  1130.             if( obj!=target_ship && class[target_ship]==ship )
  1131.                 {
  1132.                 get_facing_range_from_object(obj, target_ship);
  1133.                 if( target_range<MISSILE_SCAN_RANGE && facing_to_target>0 && target_facing<0 )
  1134.                     {
  1135.                     /*-- If ship's engines are in missile's lock arc --*/
  1136.                     viable_target[viable_target_index] = target_ship;
  1137.                     viable_target_dist[viable_target_index++] = target_range;
  1138.                     }
  1139.                 }
  1140.             }
  1141.         sort_viable_target_list();
  1142.         if (viable_target_index >0)
  1143.             {
  1144.             for (exhaust_heat = hot; exhaust_heat > cold; exhaust_heat--)
  1145.                 {
  1146.                 for (targ=0;targ<viable_target_index;targ++)
  1147.                     {
  1148.                     if (exhaust_hot[viable_target[targ]] == exhaust_heat)
  1149.                         {
  1150.                         /*-- Found a new target to lock onto --*/
  1151.                         ship_target[obj] = viable_target[targ];
  1152.                         exhaust_heat = cold;
  1153.                         break;
  1154.                         }
  1155.                     }
  1156.                 }
  1157.             }
  1158.         if (ship_target[obj] == NONE)
  1159.             explode(obj);
  1160.         }
  1161.     else
  1162.         {
  1163.         point_ship(obj, 0, &to_target);
  1164.         speed[obj] = IntToIntFract(data[type[obj]].max_velocity+10);
  1165.         }
  1166. } /* heat_seeking_missile_intelligence() */
  1167.  
  1168.  
  1169. /*
  1170. ------------------------------------------------------------------------------
  1171.     FF_missile_intelligence()
  1172. ------------------------------------------------------------------------------
  1173. */
  1174.  
  1175. void FF_missile_intelligence (int obj)
  1176. {
  1177.  int target_ship;
  1178.  
  1179.     if (ship_tactic[obj] == ram)
  1180.         {
  1181.         /*-- Missile is set to ram, after rockets have been ignited --*/
  1182.         if (ship_target[obj] == NONE)
  1183.             {
  1184.             /*-- Aquire a target for missile --*/
  1185.  
  1186.             /*--    Find the closest foe for the FF_missile to lock onto    --*/
  1187.             viable_target_index = 0;
  1188.             for (target_ship = your_ship; target_ship <= last_ship; target_ship++)
  1189.                 {
  1190.                 if (obj != target_ship)
  1191.                     {
  1192.                     if (class[target_ship] == ship)
  1193.                         {
  1194.                         if (side[target_ship] != side[parent[obj]] || communicator[target_ship] == BAD)
  1195.                             {
  1196.                             target_range  = distance_from_object(obj, target_ship);
  1197.                             if (target_range < MISSILE_SCAN_RANGE)
  1198.                                 {
  1199.                                 /*-- If ship is close enough for missile to lock onto --*/
  1200.                                 viable_target[viable_target_index] = target_ship;
  1201.                                 viable_target_dist[viable_target_index++] = target_range;
  1202.                                 }
  1203.                             }
  1204.                         }
  1205.                     }
  1206.                 }
  1207.             sort_viable_target_list();
  1208.             if (viable_target_index >0)
  1209.                 {
  1210.                 /*-- lock onto closest possible target --*/
  1211.                 ship_target[obj] = viable_target[0];
  1212.                 }
  1213.             /* If to target aquired, repeat process next turn, until missile
  1214.                 self destructs */
  1215.             }
  1216.         else
  1217.             {
  1218.             point_ship(obj, 0, &to_target);
  1219.             speed[obj] = IntToIntFract(data[type[obj]].max_velocity+10);
  1220.             }
  1221.         }
  1222. } /* FF_missile_intelligence() */
  1223.  
  1224.  
  1225.  
  1226. /* ------------------------ */
  1227.  
  1228.  
  1229. // PAUL!  what is this garbage!!! -RKLD (pci) Testing capital ship firing
  1230. x ()
  1231. {
  1232.  int it;
  1233.  
  1234.     for (it=0; it<=ships; it++)
  1235.         if (type[it] == Tigers_claw)
  1236.             {
  1237.             reset_mission_type(it,patrol);
  1238.             ship_target[it] = your_ship;
  1239.             side[it] = Kilrathi;
  1240.             }
  1241.  
  1242. } /* x() */
  1243.