]> git.pond.sub.org Git - empserver/blobdiff - src/lib/subs/mission.c
Update known contributors comments
[empserver] / src / lib / subs / mission.c
index 9a252ad3143091d7d453936caee48104e217b787..586300a0a17eeb80133598f21774ff936ec0a582 100644 (file)
@@ -1,6 +1,6 @@
 /*
  *  Empire - A multi-player, client/server Internet based war game.
- *  Copyright (C) 1986-2008, Dave Pare, Jeff Bailey, Thomas Ruschak,
+ *  Copyright (C) 1986-2009, Dave Pare, Jeff Bailey, Thomas Ruschak,
  *                           Ken Stevens, Steve McClure
  *
  *  This program is free software; you can redistribute it and/or modify
  *  ---
  *
  *  mission.c: Mission subroutines for planes/ships/units
- * 
+ *
  *  Known contributors to this file:
  *     Ken Stevens, 1995
  *     Steve McClure, 1996-2000
+ *     Markus Armbruster, 2003-2009
  */
 
 #include <config.h>
@@ -69,8 +70,8 @@ static void build_mission_list_type(struct genlist *, coord, coord, int,
 static void divide(struct emp_qelem *, struct emp_qelem *, coord, coord);
 static int dosupport(struct genlist *, coord, coord, natid, natid);
 static int find_airport(struct emp_qelem *, coord, coord);
-static int mission_pln_arm(struct emp_qelem *, coord, coord, int,
-                          int, struct ichrstr *, int, int);
+static void mission_pln_arm(struct emp_qelem *, coord, coord, int,
+                           int, struct ichrstr *, int);
 static void mission_pln_sel(struct emp_qelem *, int, int, int);
 static int perform_mission(coord, coord, natid, struct emp_qelem *, int,
                           char *, int);
@@ -289,8 +290,6 @@ build_mission_list_type(struct genlist *mi, coord x, coord y, int mission,
     struct genlist *glp;
     struct empobj *gp;
     union empobj_storage item;
-    int dist;
-    int radius;
     int relat;
     struct sctstr sect;
 
@@ -320,23 +319,8 @@ build_mission_list_type(struct genlist *mi, coord x, coord y, int mission,
        } else if (relat > HOSTILE)
            continue;
 
-       dist = mapdist(x, y, gp->opx, gp->opy);
-
-       radius = gp->radius;
-       if (mission != MI_RESERVE)      /* XXX */
-           oprange(gp, &radius);
-
-       if (dist > radius)
-           continue;
-
-       /* Ok, it is within the operations range. */
-       /* Now check from where the object actually is */
-       dist = mapdist(x, y, gp->x, gp->y);
-       radius = 999;
-       oprange(gp, &radius);
-       if (dist > radius)
+       if (!in_oparea(gp, x, y))
            continue;
-       /* Ok, the object can get to where the x,y is */
 
        if (opt_SLOW_WAR) {
            if (mission != MI_AIR_DEFENSE) {
@@ -372,20 +356,15 @@ find_escorts(coord x, coord y, natid cn, struct emp_qelem *escorts)
     struct nstr_item ni;
     struct plist *plp;
     struct plnstr plane;
-    int dist;
 
     snxtitem_all(&ni, EF_PLANE);
     while (nxtitem(&ni, &plane)) {
        if (plane.pln_own != cn)
            continue;
-
        if (plane.pln_mission != MI_ESCORT)
            continue;
-
-       dist = mapdist(x, y, plane.pln_x, plane.pln_y);
-       if (dist > plane.pln_range / 2)
+       if (!in_oparea((struct empobj *)&plane, x, y))
            continue;
-
        plp = malloc(sizeof(struct plist));
        memset(plp, 0, sizeof(struct plist));
        plp->pcp = &plchr[(int)plane.pln_type];
@@ -408,7 +387,7 @@ perform_mission(coord x, coord y, natid victim, struct emp_qelem *list,
     struct sctstr sect;
     struct mchrstr *mcp;
     struct plchrstr *pcp;
-    int dam = 0, dam2, mission_flags;
+    int dam = 0, dam2;
     natid plane_owner = 0;
     int md, range, air_dam = 0;
     double hitchance, vrange;
@@ -631,18 +610,12 @@ perform_mission(coord x, coord y, natid victim, struct emp_qelem *list,
        /* Split off the escorts at this base into e */
        divide(&escorts, &e, air->x, air->y);
 
-       mission_flags = 0;
-       mission_flags |= P_X;   /* stealth (shhh) */
-       mission_flags |= P_H;   /* gets turned off if not all choppers */
-
-       mission_flags = mission_pln_arm(&b, air->x, air->y, 2 * md, 'p', 0,
-                                       0, mission_flags);
+       mission_pln_arm(&b, air->x, air->y, 2 * md, 'p', 0, 0);
 
        if (QEMPTY(&b))
            continue;
 
-       mission_flags = mission_pln_arm(&e, air->x, air->y, 2 * md, 'p', 0,
-                                       P_F | P_ESC, mission_flags);
+       mission_pln_arm(&e, air->x, air->y, 2 * md, 'p', 0, P_F | P_ESC);
 
        pp = BestAirPath(buf, air->x, air->y, x, y);
        if (CANT_HAPPEN(!pp))
@@ -658,7 +631,7 @@ perform_mission(coord x, coord y, natid victim, struct emp_qelem *list,
               xyas(x, y, air->own));
        }
 
-       ac_encounter(&b, &e, air->x, air->y, pp, mission_flags, 0);
+       ac_encounter(&b, &e, air->x, air->y, pp, 0);
 
        if (!QEMPTY(&b))
            air_dam +=
@@ -763,93 +736,40 @@ mission_name(short mission)
     return "a mysterious";
 }
 
-void
-show_mission(int type, struct nstr_item *np)
-{
-    int first = 1, radius;
-    union empobj_storage item;
-    struct empobj *gp;
-    struct sctstr sect;
-
-    while (nxtitem(np, &item)) {
-       gp = (struct empobj *)&item;
-       if (!player->owner || gp->own == 0)
-           continue;
-
-       if (first) {
-           pr("Thing                         x,y   op-sect rad mission\n");
-           first = 0;
-       }
-       pr("%-25s", obj_nameof(gp));
-       prxy(" %3d,%-3d", gp->x, gp->y, player->cnum);
-       switch (gp->mission) {
-       case MI_INTERDICT:
-       case MI_SUPPORT:
-       case MI_AIR_DEFENSE:
-       case MI_DSUPPORT:
-       case MI_OSUPPORT:
-           radius = gp->radius;
-           oprange(gp, &radius);
-           prxy(" %3d,%-3d", gp->opx, gp->opy, player->cnum);
-           pr("  %4d", radius);
-           break;
-       case MI_RESERVE:
-           radius = item.land.lnd_rad_max;
-
-           if (radius) {
-               radius += 2;
-               getsect(gp->x, gp->y, &sect);
-               if ((sect.sct_type == SCT_HEADQ) && (sect.sct_effic >= 60))
-                   radius++;
-           }
-           prxy(" %3d,%-3d", gp->x, gp->y, player->cnum);
-           pr("  %4d", radius);
-           break;
-       case MI_ESCORT:
-           pr("        ");
-           pr("  %4d", item.plane.pln_range / 2);
-           break;
-       default:
-           CANT_REACH();
-           /* fall through */
-       case MI_NONE:
-           pr("              ");
-       }
-       if (gp->mission)
-           pr(" is on %s mission\n", mission_name(gp->mission));
-       else
-           pr(" has no mission.\n");
-    }
-}
-
+/*
+ * Maximum distance GP can perform its mission.
+ * Note: this has nothing to do with the radius of the op-area.
+ * oprange() governs where the unit *can* strike, the op-area governs
+ * where the player wants it to strike.
+ */
 int
-oprange(struct empobj *gp, int *radius)
+oprange(struct empobj *gp)
 {
-    int range;
-
     switch (gp->ef_type) {
     case EF_SHIP:
-       range = ldround(shp_fire_range((struct shpstr *)gp), 1);
-       break;
+       return ldround(shp_fire_range((struct shpstr *)gp), 1);
     case EF_LAND:
-       range = ldround(lnd_fire_range((struct lndstr *)gp), 1);
-       break;
+       if (gp->mission == MI_RESERVE)
+           return lnd_reaction_range((struct lndstr *)gp);
+       return ldround(lnd_fire_range((struct lndstr *)gp), 1);
     case EF_PLANE:
        /* missiles go one way, so we can use all the range */
        if (plchr[(int)gp->type].pl_flags & P_M)
-           range = ((struct plnstr *)gp)->pln_range;
-       else
-           range = ((struct plnstr *)gp)->pln_range / 2;
-       break;
-    default:
-       CANT_REACH();
-       range = -1;
+           return ((struct plnstr *)gp)->pln_range;
+       return ((struct plnstr *)gp)->pln_range / 2;
     }
+    CANT_REACH();
+    return -1;
+}
 
-    if (*radius > range)
-       *radius = range;
-
-    return range;
+/*
+ * Does GP's mission op area cover X,Y?
+ */
+int
+in_oparea(struct empobj *gp, coord x, coord y)
+{
+    return mapdist(x, y, gp->opx, gp->opy) <= gp->radius
+       && mapdist(x, y, gp->x, gp->y) <= oprange(gp);
 }
 
 /*
@@ -902,7 +822,7 @@ mission_pln_sel(struct emp_qelem *list, int wantflags, int nowantflags,
            free(qp);
            continue;
        }
-           
+
        if (pcp->pl_flags & P_A) {
            if (roll(100) > pln_identchance(pp, hardtarget, EF_SHIP)) {
                emp_remque(qp);
@@ -918,10 +838,9 @@ mission_pln_sel(struct emp_qelem *list, int wantflags, int nowantflags,
 /*
  * Arm only the planes at x,y
  */
-static int
+static void
 mission_pln_arm(struct emp_qelem *list, coord x, coord y, int dist,
-               int mission, struct ichrstr *ip, int flags,
-               int mission_flags)
+               int mission, struct ichrstr *ip, int flags)
 {
     struct emp_qelem *qp;
     struct emp_qelem *next;
@@ -944,32 +863,11 @@ mission_pln_arm(struct emp_qelem *list, coord x, coord y, int dist,
            free(qp);
            continue;
        }
-       if (flags & (P_S | P_I)) {
-           if (plp->pcp->pl_flags & P_S)
-               mission_flags |= P_S;
-           if (plp->pcp->pl_flags & P_I)
-               mission_flags |= P_I;
-       }
-       if (!(plp->pcp->pl_flags & P_H))
-           /* no stealth on this mission */
-           mission_flags &= ~P_H;
-       if (!(plp->pcp->pl_flags & P_X))
-           /* no stealth on this mission */
-           mission_flags &= ~P_X;
-       if (!(plp->pcp->pl_flags & P_A)) {
-           /* no asw on this mission */
-           mission_flags &= ~P_A;
-       }
-       if (!(plp->pcp->pl_flags & P_MINE)) {
-           /* no asw on this mission */
-           mission_flags &= ~P_MINE;
-       }
 
        pp->pln_flags |= PLN_LAUNCHED;
        pp->pln_mobil -= pln_mobcost(dist, pp, flags);
        putplane(pp->pln_uid, pp);
     }
-    return mission_flags;
 }
 
 int
@@ -1042,11 +940,14 @@ mission_pln_equip(struct plist *plp, struct ichrstr *ip, int flags,
        if (itype != I_NONE && needed <= 0)
            return -1;
        if (itype != I_NONE) {
-           if (itype == I_SHELL && item[itype] < needed)
-               item[itype] += supply_commod(plp->plane.pln_own,
-                                            plp->plane.pln_x,
-                                            plp->plane.pln_y,
-                                            I_SHELL, needed);
+           if (itype == I_SHELL && item[itype] < needed) {
+               if (pp->pln_ship >= 0)
+                   shp_supply(&ship, I_SHELL, needed);
+               else if (pp->pln_land >= 0)
+                   lnd_supply(&land, I_SHELL, needed);
+               else
+                   sct_supply(&sect, I_SHELL, needed);
+           }
            if (item[itype] < needed)
                return -1;
            item[itype] -= needed;
@@ -1214,223 +1115,3 @@ air_damage(struct emp_qelem *bombers, coord x, coord y, int mission,
 
     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 mission_flags, 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);
-
-           mission_flags = 0;
-           mission_flags |= P_X;       /* stealth (shhh) */
-           /* gets turned off if not all choppers */
-           mission_flags |= P_H;
-           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_flags =
-               mission_pln_arm(&i, air->x, air->y, 2 * dist, 0, 0, P_F,
-                               mission_flags);
-
-           /* 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, mission_flags, 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;
-}