]> git.pond.sub.org Git - empserver/commitdiff
Integrate air defense missions into interception
authorMarkus Armbruster <armbru@pond.sub.org>
Fri, 26 Sep 2008 01:51:21 +0000 (21:51 -0400)
committerMarkus Armbruster <armbru@pond.sub.org>
Sun, 1 Feb 2009 16:14:39 +0000 (17:14 +0100)
The ancients designed interception dead simple: when you overfly a
sector, you get intercepted by the sector owner.  Fine print
interception rules govern which planes intercept.

Then complexity got piled on top of it.

Chainsaw 2 added an extra interception by surface ship owners, in the
target sector only.

Chainsaw 3 added an extra interception by land unit owners, in the
target sector only (Empire 4 later merged this extra land unit
interception with the extra surface ship interception).

Chainsaw 3 added an entirely separate kind of interception: air
defense missions.  When you enter a sector in some air defense op
area, you get intercepted.  Fine print air defense rules govern which
planes intercept.  These rules differ significantly from the
interception fine print.

Additional complexity comes from these facts:

* Air defense mission interception happens in addition to non-mission
  interception.  You can boost your total interception by setting up
  air defense.  Which means you must set it up, or forgo an advantage.

* Air defense planes are not available for non-mission interception
  duty.  You need to decide on a split.

* In contrast to non-mission interception, interceptors flying air
  defense get intercepted.

Moreover, the air defense code breaks one of the plane code's design
assumptions, namely that just one plane sortie is active at a time.
The air defense sortie runs while the sortie it intercepts is in
progress.  This leads to two interceptions being active at the same
time: the one intercepting the original sortie, and the one
intercepting the air defense sortie.  The same plane can fly in both
interceptions, and damage received in the interception of the air
defense sortie is wiped out, triggering a seqno mismatch oops.

The previous commit already simplified non-mission interception: you
get intercepted by anyone who owns the sector, or a surface ship or a
land unit there, whether it's the target sector or not.

Now simplify mission interception, by merging air defense back into
ordinary interception: when you overfly a sector, you get intercepted
by anyone who owns the sector, or a surface ship or land unit there,
or has an air defense mission covering the sector.  That's all.  No
multiple interceptions, no separate air defense rules.

Remove air_defense().  Simplify ac_encounter() and sam_intercept()
accordingly; both lose their last parameter.

Change sam_intercept() and ac_intercept() to intercept in mission op
areas.  New parameter only_mission to suppress non-mission
interception.  Pass zero when the intercepting country owns the sector
or a surface ship or land unit in the sector.

ac_encounter() can't efficiently predict whether a country intercepts,
so it needs to call ac_intercept() unconditionally.  This kills the
optimization to collect interceptors only when needed; simplify
accordingly, replacing getilist() by getilists().

include/plane.h
include/prototypes.h
info/mission.t
src/lib/commands/bomb.c
src/lib/commands/drop.c
src/lib/commands/fly.c
src/lib/commands/para.c
src/lib/commands/reco.c
src/lib/subs/aircombat.c
src/lib/subs/mission.c

index e392050dc244db9bba59e01e975b9baded51e630..b7b3107274db9e2dd6921ff83244a3546c02e094 100644 (file)
@@ -162,13 +162,9 @@ extern int pln_first_on_land(struct lndstr *);
 extern int pln_next_on_unit(int);
 
 /* src/lib/subs/aircombat.c */
 extern int pln_next_on_unit(int);
 
 /* src/lib/subs/aircombat.c */
-extern void ac_combat_headers(natid, natid);
-extern void ac_airtoair(struct emp_qelem *, struct emp_qelem *);
 extern int ac_flak_dam(int, int, int);
 extern void ac_encounter(struct emp_qelem *, struct emp_qelem *, coord,
 extern int ac_flak_dam(int, int, int);
 extern void ac_encounter(struct emp_qelem *, struct emp_qelem *, coord,
-                        coord, char *, int, int);
-extern void sam_intercept(struct emp_qelem *, struct emp_qelem *,
-                         natid, natid, coord, coord, int);
+                        coord, char *, int);
 
 /* src/lib/subs/aswplnsubs.c */
 extern int on_shiplist(short, struct shiplist *);
 
 /* src/lib/subs/aswplnsubs.c */
 extern int on_shiplist(short, struct shiplist *);
index ac11292246b5941c6218e123e5214aef3163dbb6..5c58835a33a13c4eab27430b07421c201eddc9d7 100644 (file)
@@ -488,8 +488,6 @@ extern int def_support(coord, coord, natid, natid);
 extern int oprange(struct empobj *);
 extern int in_oparea(struct empobj *, coord, coord);
 extern int cando(int, int);
 extern int oprange(struct empobj *);
 extern int in_oparea(struct empobj *, coord, coord);
 extern int cando(int, int);
-extern int air_defense(coord, coord, natid, struct emp_qelem *,
-                      struct emp_qelem *);
 /* move.c */
 extern int check_lmines(coord, coord, double);
 extern int move_ground(struct sctstr *, struct sctstr *,
 /* move.c */
 extern int check_lmines(coord, coord, double);
 extern int move_ground(struct sctstr *, struct sctstr *,
index 732fe606f0624de6520e087af8fe8975e5b071e3..3f8a2443e7162faf111773a73005b686e444e7e2 100644 (file)
@@ -36,14 +36,13 @@ or "order").
 .s1
 Artillery units less than 40% efficient will not fire.
 .s1
 .s1
 Artillery units less than 40% efficient will not fire.
 .s1
-Planes flying missions will be intercepted normally. (i.e. if you fly
-over enemy territory, you'll get intercepted. Any mission except air
-missions may also be intercepted by planes on air defense missions)
+Planes flying missions other than air defense will be intercepted
+normally. (i.e. if you fly over enemy territory, you'll get
+intercepted.
 .s1
 .s1
-Planes of less than 40% efficiency will not fly missions.
-.s1
-Planes assigned to missions are \*QNOT\*U eligible to intercept
-normally. For example, if a fighter is assigned to an escort or air-defense
+Planes assigned to missions other than air defense are \*QNOT\*U
+eligible to intercept normally. For example, if a fighter is assigned
+to an escort
 or interdiction or support mission, it will \*QNOT\*U rise to intercept
 an intruding enemy plane. (planes on air-defense missions will intercept
 planes flying in their op-area, in accordance with the air-defense mission,
 or interdiction or support mission, it will \*QNOT\*U rise to intercept
 an intruding enemy plane. (planes on air-defense missions will intercept
 planes flying in their op-area, in accordance with the air-defense mission,
@@ -232,22 +231,11 @@ pays to put your bombing planes and escorting planes together.
 Only planes with the 'escort' or 'intercept' abilities can fly escort missions.
 .s1
 AIR DEFENSE MISSIONS (planes only)
 Only planes with the 'escort' or 'intercept' abilities can fly escort missions.
 .s1
 AIR DEFENSE MISSIONS (planes only)
-When given an air defense mission, an intercept capable plane will attempt
-to intercept any enemy plane (defined as any plane belonging to a country
-you re at war with) flying into its operations area, irregardless
-of whether the enemy planes are flying over owned sectors. For example, if
-a plane is given an air defense mission with an op area covering some
-owned sectors, some sea, some allied sectors, and some enemy sectors, it
-would try to intercept over any of them.
-.s1
-When a plane enters a sector, any planes with air defense missions that are
-at war with the owner of the plane will fly there to fight it.
-The air defense planes
-encounter normal interception along the way (but do \*QNOT\*U trigger
-more air defense missions, but \*QMAY\*U be intercepted normally).
-Once the air defense planes get to the sector,
-they fight the plane. Then, if the owner of the sector
-is hostile to the plane, still more planes may intercept it.
+.s1
+Putting a plane on an air defense mission modifies where the plane
+intercepts.  Without a mission, it intercepts over own sectors,
+surface ships and land units.  With an air defense mission, it
+intercepts over any sector in its op area.
 .s1
 .L Example
 Groonland wants to run a recon flight over Bannannarama. Joeland has a
 .s1
 .L Example
 Groonland wants to run a recon flight over Bannannarama. Joeland has a
@@ -275,12 +263,10 @@ This is within the Joeland aircraft's op-area, so it flies to intercept.
 It takes the shortest path there, and fights the Groonland plane.
 Let's say that both take 20 points of damage, and neither aborts.
 .s1
 It takes the shortest path there, and fights the Groonland plane.
 Let's say that both take 20 points of damage, and neither aborts.
 .s1
-Next, the Groonland plane overflies a Bannannarama sector. The Joeland
-plane flies there, and is intercepted by the Bannannarama plane. Let's
-say that it comes through the fight without being aborted. It then fights
-the Groonland plane. After this combat, if the Groonland plane is not
-aborted, it may be intercepted again by the busy Bannannarama fighter,
-assuming that that plane is still efficient enough, has mob enough, etc.
+Next, the Groonland plane overflies a Bannannarama sector.  It gets
+intercepted by Joeland's fighter, because the sector is in its
+op-area, and by Bannannarama's fighter, because the sector belongs to
+Bannannarama.  And so forth.
 .s1
 A good use of this mission is to provide a wider CAP around a carrier,
 so that enemy planes get intercepted several times on the way to the
 .s1
 A good use of this mission is to provide a wider CAP around a carrier,
 so that enemy planes get intercepted several times on the way to the
index 87c29d4676f5b60cbda8f0a479dfa9d662685dc8..a0bfe704faa1bd9507a0a2a17829a1699b44d989 100644 (file)
@@ -140,7 +140,7 @@ bomb(void)
        return RET_FAIL;
     }
     pln_arm(&esc_list, 2 * ap_to_target, mission, ip, P_F | P_ESC);
        return RET_FAIL;
     }
     pln_arm(&esc_list, 2 * ap_to_target, mission, ip, P_F | P_ESC);
-    ac_encounter(&bomb_list, &esc_list, ax, ay, flightpath, 0, 0);
+    ac_encounter(&bomb_list, &esc_list, ax, ay, flightpath, 0);
     if (QEMPTY(&bomb_list)) {
        pr("No planes got through fighter defenses\n");
     } else if (target.sct_type == SCT_SANCT) {
     if (QEMPTY(&bomb_list)) {
        pr("No planes got through fighter defenses\n");
     } else if (target.sct_type == SCT_SANCT) {
index 2c8806eb4afcd5c8b0590f1ab705b1250ba05515..247b4fbac301c4fcb5adffff314ca1bea7922f53 100644 (file)
@@ -115,7 +115,7 @@ drop(void)
        return RET_FAIL;
     }
     pln_arm(&esc_list, 2 * ap_to_target, 'd', ip, P_ESC | P_F);
        return RET_FAIL;
     }
     pln_arm(&esc_list, 2 * ap_to_target, 'd', ip, P_ESC | P_F);
-    ac_encounter(&bomb_list, &esc_list, ax, ay, flightpath, 0, 0);
+    ac_encounter(&bomb_list, &esc_list, ax, ay, flightpath, 0);
     if (QEMPTY(&bomb_list)) {
        pr("No planes got through fighter defenses\n");
     } else {
     if (QEMPTY(&bomb_list)) {
        pr("No planes got through fighter defenses\n");
     } else {
index efc60696fd4a34e2519050d54fcb095fa27d488b..130c32b8e8d1e0a44c90fb34130662af8adf5e4f 100644 (file)
@@ -117,8 +117,7 @@ fly(void)
        return RET_FAIL;
     }
     pln_arm(&esc_list, ap_to_target, 't', ip, P_ESC | P_F);
        return RET_FAIL;
     }
     pln_arm(&esc_list, ap_to_target, 't', ip, P_ESC | P_F);
-    ac_encounter(&bomb_list, &esc_list, ax, ay,
-                flightpath, 0, 0);
+    ac_encounter(&bomb_list, &esc_list, ax, ay, flightpath, 0);
     if (QEMPTY(&bomb_list)) {
        pr("No planes got through fighter defenses\n");
     } else {
     if (QEMPTY(&bomb_list)) {
        pr("No planes got through fighter defenses\n");
     } else {
index 8299f33a3ac33ce82e04c14f5812a85775742328..142d02d8aec3989f983337b3653921b209cfa77f 100644 (file)
@@ -96,7 +96,7 @@ para(void)
        return RET_FAIL;
     }
     pln_arm(&esc_list, 2 * ap_to_target, 'a', &ichr[I_MILIT], P_ESC | P_F);
        return RET_FAIL;
     }
     pln_arm(&esc_list, 2 * ap_to_target, 'a', &ichr[I_MILIT], P_ESC | P_F);
-    ac_encounter(&bomb_list, &esc_list, ax, ay, flightpath, 0, 0);
+    ac_encounter(&bomb_list, &esc_list, ax, ay, flightpath, 0);
     if (QEMPTY(&bomb_list)) {
        pr("No planes got through fighter defenses\n");
     } else {
     if (QEMPTY(&bomb_list)) {
        pr("No planes got through fighter defenses\n");
     } else {
index e60b0229e252dc3beb0b12f1be778eb613c01f62..5f89c0b7799cb18aa5d772765ec76618253d9e00 100644 (file)
@@ -104,8 +104,7 @@ reco(void)
     }
     pln_arm(&esc_list, ap_to_target, 'r', 0, P_F | P_ESC);
     ac_encounter(&bomb_list, &esc_list, ax, ay, flightpath,
     }
     pln_arm(&esc_list, ap_to_target, 'r', 0, P_F | P_ESC);
     ac_encounter(&bomb_list, &esc_list, ax, ay, flightpath,
-                *player->argp[0] == 's' ? PM_R | PM_S : PM_R,
-                0);
+                *player->argp[0] == 's' ? PM_R | PM_S : PM_R);
     if (QEMPTY(&bomb_list)) {
        pr("No planes got through fighter defenses\n");
     } else {
     if (QEMPTY(&bomb_list)) {
        pr("No planes got through fighter defenses\n");
     } else {
index 8413a102a144f2b8381fe66630854b989ab50432..c95e0f0fa3ef9a6cbf94348f8401fe9d644601fe 100644 (file)
@@ -40,6 +40,7 @@
 #include "land.h"
 #include "map.h"
 #include "misc.h"
 #include "land.h"
 #include "map.h"
 #include "misc.h"
+#include "mission.h"
 #include "nat.h"
 #include "news.h"
 #include "nsc.h"
 #include "nat.h"
 #include "news.h"
 #include "nsc.h"
 #define FLAK_GUN_MAX 14
 
 static int plane_caps(struct emp_qelem *);
 #define FLAK_GUN_MAX 14
 
 static int plane_caps(struct emp_qelem *);
+static void sam_intercept(struct emp_qelem *, struct emp_qelem *,
+                         natid, natid, coord, coord, int);
 static void ac_intercept(struct emp_qelem *, struct emp_qelem *,
 static void ac_intercept(struct emp_qelem *, struct emp_qelem *,
-                        struct emp_qelem *, natid, coord, coord);
+                        struct emp_qelem *, natid, coord, coord, int);
+static void ac_combat_headers(natid, natid);
+static void ac_airtoair(struct emp_qelem *, struct emp_qelem *);
 static void ac_dog(struct plist *, struct plist *);
 static void ac_planedamage(struct plist *, natid, int, natid, int,
                           int, char *);
 static void ac_dog(struct plist *, struct plist *);
 static void ac_planedamage(struct plist *, natid, int, natid, int,
                           int, char *);
@@ -64,19 +69,17 @@ static void ac_doflak(struct emp_qelem *, struct sctstr *);
 static void ac_landflak(struct emp_qelem *, coord, coord);
 static void ac_shipflak(struct emp_qelem *, coord, coord);
 static void ac_fireflak(struct emp_qelem *, natid, int);
 static void ac_landflak(struct emp_qelem *, coord, coord);
 static void ac_shipflak(struct emp_qelem *, coord, coord);
 static void ac_fireflak(struct emp_qelem *, natid, int);
-static void getilist(struct emp_qelem *, natid);
+static void getilists(struct emp_qelem *, unsigned char *, natid);
 static int do_evade(struct emp_qelem *, struct emp_qelem *);
 
 void
 ac_encounter(struct emp_qelem *bomb_list, struct emp_qelem *esc_list,
 static int do_evade(struct emp_qelem *, struct emp_qelem *);
 
 void
 ac_encounter(struct emp_qelem *bomb_list, struct emp_qelem *esc_list,
-            coord x, coord y, char *path, int mission_flags,
-            int no_air_defense)
+            coord x, coord y, char *path, int mission_flags)
 {
     int val;
     int dir;
     unsigned char gotships[MAXNOC];
     unsigned char gotlands[MAXNOC];
 {
     int val;
     int dir;
     unsigned char gotships[MAXNOC];
     unsigned char gotlands[MAXNOC];
-    int gotilist[MAXNOC];
     unsigned char rel[MAXNOC];
     int overfly[MAXNOC];
     int flags;
     unsigned char rel[MAXNOC];
     int overfly[MAXNOC];
     int flags;
@@ -100,9 +103,7 @@ ac_encounter(struct emp_qelem *bomb_list, struct emp_qelem *esc_list,
     plane_owner = plp->plane.pln_own;
 
     memset(overfly, 0, sizeof(overfly));
     plane_owner = plp->plane.pln_own;
 
     memset(overfly, 0, sizeof(overfly));
-    memset(gotilist, 0, sizeof(gotilist));
-    for (cn = 0; cn < MAXNOC; cn++)
-       rel[cn] = getrel(getnatp(cn), plane_owner);
+    getilists(ilist, rel, plane_owner);
 
     if (mission_flags & PM_R) {
        flags = plane_caps(bomb_list);
 
     if (mission_flags & PM_R) {
        flags = plane_caps(bomb_list);
@@ -228,19 +229,12 @@ ac_encounter(struct emp_qelem *bomb_list, struct emp_qelem *esc_list,
            if (QEMPTY(bomb_list))
                break;
 
            if (QEMPTY(bomb_list))
                break;
 
-           if (!no_air_defense)
-               air_defense(x, y, plane_owner, bomb_list, esc_list);
-
            for (cn = 1; cn < MAXNOC && !QEMPTY(bomb_list); cn++) {
                if (rel[cn] > HOSTILE)
                    continue;
            for (cn = 1; cn < MAXNOC && !QEMPTY(bomb_list); cn++) {
                if (rel[cn] > HOSTILE)
                    continue;
-               if (cn != sect.sct_own && !gotships[cn] && !gotlands[cn])
-                   continue;
-               if (!gotilist[cn]) {
-                   getilist(&ilist[cn], cn);
-                   gotilist[cn]++;
-               }
-               ac_intercept(bomb_list, esc_list, &ilist[cn], cn, x, y);
+               ac_intercept(bomb_list, esc_list, &ilist[cn], cn, x, y,
+                            !(cn == sect.sct_own
+                              || gotships[cn] || gotlands[cn]));
            }
        }
 
            }
        }
 
@@ -263,10 +257,8 @@ ac_encounter(struct emp_qelem *bomb_list, struct emp_qelem *esc_list,
        writemap(player->cnum);
 
     free_shiplist(&head);
        writemap(player->cnum);
 
     free_shiplist(&head);
-    for (cn = 1; cn < MAXNOC; cn++) {
-       if (gotilist[cn])
-           pln_put(&ilist[cn]);
-    }
+    for (cn = 1; cn < MAXNOC; cn++)
+       pln_put(&ilist[cn]);
 }
 
 static int
 }
 
 static int
@@ -285,10 +277,10 @@ plane_caps(struct emp_qelem *list)
     return fl;
 }
 
     return fl;
 }
 
-void
+static void
 sam_intercept(struct emp_qelem *att_list, struct emp_qelem *def_list,
              natid def_own, natid plane_owner, coord x, coord y,
 sam_intercept(struct emp_qelem *att_list, struct emp_qelem *def_list,
              natid def_own, natid plane_owner, coord x, coord y,
-             int delete_missiles)
+             int only_mission)
 {
     struct emp_qelem *aqp;
     struct emp_qelem *anext;
 {
     struct emp_qelem *aqp;
     struct emp_qelem *anext;
@@ -296,6 +288,7 @@ sam_intercept(struct emp_qelem *att_list, struct emp_qelem *def_list,
     struct emp_qelem *dnext;
     struct plist *aplp;
     struct plist *dplp;
     struct emp_qelem *dnext;
     struct plist *aplp;
     struct plist *dplp;
+    struct plnstr *pp;
     int first = 1;
 
     for (aqp = att_list->q_forw,
     int first = 1;
 
     for (aqp = att_list->q_forw,
@@ -308,20 +301,24 @@ sam_intercept(struct emp_qelem *att_list, struct emp_qelem *def_list,
        for (; dqp != def_list; dqp = dnext) {
            dnext = dqp->q_forw;
            dplp = (struct plist *)dqp;
        for (; dqp != def_list; dqp = dnext) {
            dnext = dqp->q_forw;
            dplp = (struct plist *)dqp;
+           pp = &dplp->plane;
            if (!(dplp->pcp->pl_flags & P_M))
                continue;
            if (!(dplp->pcp->pl_flags & P_M))
                continue;
-
-           if (dplp->plane.pln_range <
-               mapdist(x, y, dplp->plane.pln_x, dplp->plane.pln_y))
+           if (only_mission && !pp->pln_mission)
                continue;
                continue;
-           if (CANT_HAPPEN(dplp->plane.pln_flags & PLN_LAUNCHED)
+           if (pp->pln_range < mapdist(x, y, pp->pln_x, pp->pln_y))
+               continue;
+           if (pp->pln_mission
+               && pp->pln_radius < mapdist(x, y, pp->pln_opx, pp->pln_opy))
+               continue;
+           if (CANT_HAPPEN(pp->pln_flags & PLN_LAUNCHED)
                || mission_pln_equip(dplp, 0, P_F, 0) < 0) {
                emp_remque(dqp);
                free(dqp);
                continue;
            }
                || mission_pln_equip(dplp, 0, P_F, 0) < 0) {
                emp_remque(dqp);
                free(dqp);
                continue;
            }
-           dplp->plane.pln_flags |= PLN_LAUNCHED;
-           putplane(dplp->plane.pln_uid, &dplp->plane);
+           pp->pln_flags |= PLN_LAUNCHED;
+           putplane(pp->pln_uid, pp);
            if (first) {
                first = 0;
                PR(plane_owner, "%s launches SAMs!\n", cname(def_own));
            if (first) {
                first = 0;
                PR(plane_owner, "%s launches SAMs!\n", cname(def_own));
@@ -338,22 +335,12 @@ sam_intercept(struct emp_qelem *att_list, struct emp_qelem *def_list,
        PR(plane_owner, "\n");
        PR(def_own, "\n");
     }
        PR(plane_owner, "\n");
        PR(def_own, "\n");
     }
-    if (delete_missiles) {
-       for (; dqp != def_list; dqp = dnext) {
-           dnext = dqp->q_forw;
-           dplp = (struct plist *)dqp;
-           if (!(dplp->pcp->pl_flags & P_M))
-               continue;
-           emp_remque(dqp);
-           free(dqp);
-           continue;
-       }
-    }
 }
 
 static void
 ac_intercept(struct emp_qelem *bomb_list, struct emp_qelem *esc_list,
 }
 
 static void
 ac_intercept(struct emp_qelem *bomb_list, struct emp_qelem *esc_list,
-            struct emp_qelem *def_list, natid def_own, coord x, coord y)
+            struct emp_qelem *def_list, natid def_own, coord x, coord y,
+            int only_mission)
 {
     struct plnstr *pp;
     struct plist *plp;
 {
     struct plnstr *pp;
     struct plist *plp;
@@ -368,8 +355,10 @@ ac_intercept(struct emp_qelem *bomb_list, struct emp_qelem *esc_list,
     plp = (struct plist *)bomb_list->q_forw;
     plane_owner = plp->plane.pln_own;
 
     plp = (struct plist *)bomb_list->q_forw;
     plane_owner = plp->plane.pln_own;
 
-    sam_intercept(bomb_list, def_list, def_own, plane_owner, x, y, 0);
-    sam_intercept(esc_list, def_list, def_own, plane_owner, x, y, 0);
+    sam_intercept(bomb_list, def_list, def_own, plane_owner, x, y,
+                 only_mission);
+    sam_intercept(esc_list, def_list, def_own, plane_owner, x, y,
+                 only_mission);
 
     att_count = 0;
     for (qp = bomb_list->q_forw; qp != bomb_list; qp = qp->q_forw)
 
     att_count = 0;
     for (qp = bomb_list->q_forw; qp != bomb_list; qp = qp->q_forw)
@@ -388,9 +377,14 @@ ac_intercept(struct emp_qelem *bomb_list, struct emp_qelem *esc_list,
        /* SAMs interdict separately */
        if (plp->pcp->pl_flags & P_M)
            continue;
        /* SAMs interdict separately */
        if (plp->pcp->pl_flags & P_M)
            continue;
+       if (only_mission && !pp->pln_mission)
+           continue;
        dist = mapdist(x, y, pp->pln_x, pp->pln_y) * 2;
        if (pp->pln_range < dist)
            continue;
        dist = mapdist(x, y, pp->pln_x, pp->pln_y) * 2;
        if (pp->pln_range < dist)
            continue;
+       if (pp->pln_mission
+           && pp->pln_radius < mapdist(x, y, pp->pln_opx, pp->pln_opy))
+           continue;
        if (CANT_HAPPEN(pp->pln_flags & PLN_LAUNCHED)
            || mission_pln_equip(plp, 0, P_F, 0) < 0) {
            emp_remque(qp);
        if (CANT_HAPPEN(pp->pln_flags & PLN_LAUNCHED)
            || mission_pln_equip(plp, 0, P_F, 0) < 0) {
            emp_remque(qp);
@@ -845,27 +839,33 @@ ac_flak_dam(int guns, int def, int pl_flags)
 }
 
 /*
 }
 
 /*
- * Get a list of planes available for interception duties.
+ * Get planes available for interception duties.
  */
 static void
  */
 static void
-getilist(struct emp_qelem *list, natid own)
+getilists(struct emp_qelem *list, unsigned char *rel, natid intruder)
 {
 {
+    natid cn;
     struct plchrstr *pcp;
     struct plnstr plane;
     struct nstr_item ni;
     struct plist *ip;
 
     struct plchrstr *pcp;
     struct plnstr plane;
     struct nstr_item ni;
     struct plist *ip;
 
-    emp_initque(list);
+    rel[0] = NEUTRAL;
+    for (cn = 1; cn < MAXNOC; cn++) {
+       rel[cn] = getrel(getnatp(cn), intruder);
+       emp_initque(&list[cn]);
+    }
+
     snxtitem_all(&ni, EF_PLANE);
     while (nxtitem(&ni, &plane)) {
     snxtitem_all(&ni, EF_PLANE);
     while (nxtitem(&ni, &plane)) {
-       if (plane.pln_own != own)
+       if (rel[plane.pln_own] > HOSTILE)
            continue;
        pcp = &plchr[(int)plane.pln_type];
        if ((pcp->pl_flags & P_F) == 0)
            continue;
        if (plane.pln_flags & PLN_LAUNCHED)
            continue;
            continue;
        pcp = &plchr[(int)plane.pln_type];
        if ((pcp->pl_flags & P_F) == 0)
            continue;
        if (plane.pln_flags & PLN_LAUNCHED)
            continue;
-       if (plane.pln_mission != 0)
+       if (plane.pln_mission && plane.pln_mission != MI_AIR_DEFENSE)
            continue;
        if (plane.pln_mobil <= 0)
            continue;
            continue;
        if (plane.pln_mobil <= 0)
            continue;
@@ -879,7 +879,7 @@ getilist(struct emp_qelem *list, natid own)
        ip->misc = 0;
        ip->pcp = &plchr[(int)plane.pln_type];
        ip->plane = plane;
        ip->misc = 0;
        ip->pcp = &plchr[(int)plane.pln_type];
        ip->plane = plane;
-       emp_insque(&ip->queue, list);
+       emp_insque(&ip->queue, &list[plane.pln_own]);
     }
 }
 
     }
 }
 
index e3d78f8c7d0a75a1479d807f5dfefea327d65a09..473e012dd5ce021822c435541ac58a5ead90e510 100644 (file)
@@ -630,7 +630,7 @@ perform_mission(coord x, coord y, natid victim, struct emp_qelem *list,
               xyas(x, y, air->own));
        }
 
               xyas(x, y, air->own));
        }
 
-       ac_encounter(&b, &e, air->x, air->y, pp, 0, 0);
+       ac_encounter(&b, &e, air->x, air->y, pp, 0);
 
        if (!QEMPTY(&b))
            air_dam +=
 
        if (!QEMPTY(&b))
            air_dam +=
@@ -1111,216 +1111,3 @@ air_damage(struct emp_qelem *bombers, coord x, coord y, int mission,
 
     return dam;
 }
 
     return dam;
 }
-
-/*
- * Check to see if anyone hostile to the victim
- * is running an air defense mission on this
- * sector. If so, do air combat
- */
-int
-air_defense(coord x, coord y, natid victim, struct emp_qelem *bomb_list,
-           struct emp_qelem *esc_list)
-{
-    int dam = 0, cn;
-    int combat = 0, rel, dist, z;
-    struct emp_qelem *qp, interceptors, airp, i, empty, *next;
-    struct plist *plp;
-    struct genlist *glp;
-    struct empobj *gp;
-    struct genlist mi[MAXNOC];
-    char buf[512];
-    char *path;
-    int count;
-    int tcount;
-
-    count = 0;
-    for (qp = bomb_list->q_forw; qp != bomb_list; qp = qp->q_forw)
-       count++;
-    for (qp = esc_list->q_forw; qp != esc_list; qp = qp->q_forw)
-       count++;
-
-    memset(mi, 0, sizeof(mi));
-    for (z = 1; z < MAXNOC; z++)
-       emp_initque((struct emp_qelem *)&mi[z]);
-
-    build_mission_list_type(mi, x, y, MI_AIR_DEFENSE, EF_PLANE, victim);
-
-    for (cn = 1; cn < MAXNOC; cn++) {
-       /* Check our relations */
-       rel = getrel(getnatp(cn), victim);
-
-       if (rel > HOSTILE)
-           continue;
-
-       if (QEMPTY(&mi[cn].queue))
-           continue;
-
-       /* Ok, make a list of all the interceptors.  Note that this *copies* the
-        * list from the mission creation.  This list must be deleted later. */
-       emp_initque(&interceptors);
-       for (qp = mi[cn].queue.q_forw; qp != (&mi[cn].queue); qp = next) {
-           next = qp->q_forw;
-           glp = (struct genlist *)qp;
-           gp = glp->thing;
-           if (CANT_HAPPEN(gp->ef_type != EF_PLANE))
-               break;
-
-           dist = mapdist(x, y, gp->x, gp->y);
-
-           plp = malloc(sizeof(struct plist));
-           memset(plp, 0, sizeof(struct plist));
-           plp->pcp = glp->cp;
-           memcpy(&plp->plane, glp->thing, sizeof(struct plnstr));
-
-           /* missiles go one way, so we can use all the range */
-           if (!(plp->pcp->pl_flags & P_M))
-               dist *= 2;
-           /* If it's out of range, free it and continue on */
-           if (dist > plp->plane.pln_range) {
-               free(plp);
-               continue;
-           }
-           emp_insque(&plp->queue, &interceptors);
-       }
-
-       /* Remove those who cannot go */
-       mission_pln_sel(&interceptors, P_F, 0, SECT_HARDTARGET);
-
-       if (QEMPTY(&interceptors))
-           continue;
-
-       /* Now, delete all the extras, but delete the first ones, not the last ones, so
-        * that the higher numbered planes go into battle (they should be the better ones
-        * at fighting, if all went well.) */
-       tcount = 0;
-       for (qp = interceptors.q_forw; qp != (&interceptors);
-            qp = qp->q_forw)
-           tcount++;
-       tcount -= count * 2;
-       /* Just in case there are more incoming than we have */
-       if (tcount < 0)
-           tcount = 0;
-       for (qp = interceptors.q_forw; qp != (&interceptors); qp = next) {
-           next = qp->q_forw;
-           if (tcount) {
-               tcount--;
-               /* Free it up and continue */
-               emp_remque(qp);
-               glp = (struct genlist *)qp;
-               free(glp);
-           }
-       }
-
-       /* Now, make a list of all the airports these planes are coming from */
-       emp_initque(&airp);
-       for (qp = interceptors.q_forw; qp != (&interceptors);
-            qp = qp->q_forw) {
-           plp = (struct plist *)qp;
-           if (!find_airport(&airp, plp->plane.pln_x, plp->plane.pln_y))
-               add_airport(&airp, plp->plane.pln_x, plp->plane.pln_y);
-       }
-
-       /* Now, fly them out one airport at a time */
-       for (qp = airp.q_forw; qp != (&airp); qp = qp->q_forw) {
-           struct airport *air;
-
-           air = (struct airport *)qp;
-           dist = mapdist(x, y, air->x, air->y);
-
-           emp_initque(&i);
-
-           /* Split off the interceptors at this base into i */
-           divide(&interceptors, &i, air->x, air->y);
-
-           sam_intercept(bomb_list, &i, cn, victim, x, y, 0);
-           sam_intercept(esc_list, &i, cn, victim, x, y, 1);
-
-           /* Did we run out of interceptors? */
-           if (QEMPTY(&i))
-               continue;
-           /* Did we run out of bombers? */
-           if (QEMPTY(bomb_list)) {
-               /* Yes, so we have to put the rest of the interceptors back, and
-                  then continue, or we leak memory */
-               pln_put(&i);
-               continue;
-           }
-           mission_pln_arm(&i, air->x, air->y, 2 * dist, 0, 0, P_F);
-
-           /* Did we run out of interceptors? */
-           if (QEMPTY(&i))
-               continue;
-           /* Did we run out of bombers? */
-           if (QEMPTY(bomb_list)) {
-               /* Yes, so we have to put the rest of the interceptors back, and
-                  then continue, or we leak memory */
-               pln_put(&i);
-               continue;
-           }
-
-           path = BestAirPath(buf, air->x, air->y, x, y);
-           if (CANT_HAPPEN(!path)) {
-               pln_put(&i);
-               continue;
-           }
-           wu(0, cn, "Flying %s mission from %s to %s\n",
-              mission_name(MI_AIR_DEFENSE),
-              xyas(air->x, air->y, cn),
-              xyas(x, y, cn));
-           if (air->own && (air->own != cn)) {
-               wu(0, air->own, "%s is flying %s mission from %s to %s\n",
-                  cname(cn), mission_name(MI_AIR_DEFENSE),
-                  xyas(air->x, air->y, air->own),
-                  xyas(x, y, air->own));
-           }
-
-           /* Now, fly the planes to the sector */
-           emp_initque(&empty);
-           ac_encounter(&i, &empty, air->x, air->y, path, 0, 1);
-
-           /* If none made it, continue */
-           if (QEMPTY(&i))
-               continue;
-
-           /* Some made it, so now they get to try to fight. */
-           /* Intercept the escorts first */
-           combat = 0;
-           if (!QEMPTY(esc_list)) {
-               mpr(victim, "%s air defense planes intercept!\n",
-                   cname(cn));
-               ac_combat_headers(victim, cn);
-               ac_airtoair(esc_list, &i);
-               combat = 1;
-           }
-           /* Now intercept the bombers */
-           if (!QEMPTY(bomb_list)) {
-               if (!combat) {
-                   mpr(victim, "%s air defense planes intercept!\n",
-                       cname(cn));
-                   ac_combat_headers(victim, cn);
-               }
-               ac_airtoair(bomb_list, &i);
-               PR(cn, "\n");
-               PR(victim, "\n");
-           }
-
-           pln_put(&i);
-       }
-       if (CANT_HAPPEN(!QEMPTY(&interceptors)))
-           pln_put(&interceptors);
-    }
-
-    /* We have to free all of these, if they are still there, otherwise they get
-       lost and we leak memory all over the place. */
-    for (cn = 1; cn < MAXNOC; cn++) {
-       /* free up all this memory if it's still there */
-       for (qp = mi[cn].queue.q_forw; qp != (&mi[cn].queue); qp = next) {
-           next = qp->q_forw;
-           glp = (struct genlist *)qp;
-           free(glp->thing);
-           free(glp);
-       }
-    }
-
-    return dam;
-}